JS:劫持(call apply bind)

劫持一般有三类:

1、黑客劫持网站,隐私数据,个人信息等

2、通过劫持重置系统内置函数

3、this的引用劫持

 

接下来主要介绍this的引用劫持

*通过函数call apply bind也可以重置系统内置函数;

 

1、call

方法:就是调用所有者对象作为参数的方法,可以自定义接收者来调用函数

语法:call(this: Function, thisArg: any, ...argArray: any[]): any

实例:

        var obj = {};
        var arr = [];
        function fn(arg1,arg2) {
            console.log(this);
        };
        fn.call(obj);    //{}
        fn.call(arr);    //[]
        fn.call(null);    //window{...}
        fn.call(1);    //Number {1}
        fn.call(false);    //Boolean {false}
        fn.call(undefined);    //window{...}

 

2、apply

方法:能劫持另外一个对象的方法,继承另外一个对象的属性

语法:apply(this: Function, thisArg: any, argArray?: any): any

Function.apply(obj,args)方法能接收两个参数,除了obj也可以是数组

实例:

        var obj1 = {
            name: 'lili'
        };

        function fn() {
            console.log(this);
        }
        fn.apply(obj1);     //{name: 'lili'}
        fn.apply(1);     //Number {1}
        fn.apply(true);     //Boolean {true}
        fn.apply([]);     //[]
        fn.apply(undefined);     //window{...}
        fn.apply();     //window{...}    

 

call() 和 apply() 之间的区别:

call() 方法分别接受参数。

apply() 方法接受数组形式的参数。

如果要使用数组而不是参数列表,则 apply() 方法非常方便。

 

 

3、bind

方法:简单来说就是将函数绑定到某个对象;

语法:bind(this: Function, thisArg: any, ...argArray: any[]): any

fn.bind(obj)==>obj.fn(),函数内的this指向obj

实例:

        var obj = {
            name: 'jack'
        };
        var obj1 = {
            name: 'lili',
            fn: function () {
                console.log(this);
            }.bind(obj),
        }
        obj1.fn();    //{name: 'jack'}
        obj1.fn.call(obj);    //{name: 'jack'}
        obj1.fn.apply(obj);     //{name: 'jack'}

 

call、apply

        var obj = {
            name: 'lili'
        };
        var obj2 = {
            age : 10
        }
        var obj1 = {
            name: 'lili',
            fn: function () {
                console.log(this);
            }
        }
        obj1.fn(); //{name: 'lili', fn: ƒ}
        obj1.fn.call(obj); //{name: 'lili'}
        obj1.fn.apply(obj2); //{age: 10}

 

4、fn.call.call()方法

(1)

        function fn () {
            console.log(1,this)
        }
        function fn2 () {
            console.log(2,this)
        }
        fn.call(fn2)

打印结果:

        1 ƒ fn2 () {
            console.log(2,this)
        }

我们可以看到,虽然更换了调用对象,但是打印的还是1,但this已经指向了fn2

 

(2)

        function fn () {
            console.log(1,this);
        }
        function fn2 () {
            console.log(2,this);
        }
        fn.call.call(fn2);

打印结果:

    2 Window {window: Window, self: Window, document: document, name: '', location: Location, …}

*这个过程执行是从 call(fn2)开始的,把this指向fn2;

*call(fn2) 前面的this 改成了fn2 ,前面方法照常执行;

fn1.call.call 的主体(this)是 fn1.call, 所以fn1.call变成fn2

*call(fn2) 前面是fn1.call 改变this 后,fn1 变成了 fn2,所以接下来执行的就是 fn2.call()

 

总结:

当有两个或以上的call,在第二步时改变了this指向,无论有多少call(fn1.call....call(fn2)),都是相当于fn2

 

posted on 2022-06-26 15:40  香香鲲  阅读(302)  评论(0编辑  收藏  举报