Geek-James/Blog

5.call apply bind 小结

Geek-James opened this issue · 6 comments

apply()

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数

语法:

fun.apply(thisArg, [argsArray])
  • thisArg:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。

  • argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。

apply 和 call 的区别

其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。

语法:

fun.call(thisArg[, arg1[, arg2[, ...]]])

所以 apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。

    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    // 接受的是一个数组
    b.apply(a,[1,2])     // 3
    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    // 接受的是参数
    b.call(a,1,2)       // 3

bind 和 apply、call 区别

    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    b.bind(a,1,2)

以上code我们会发现并没有输出.

bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:

    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    b.bind(a,1,2)()           // 3

一个面试经典问题:new 的过程了

伪代码

var a = new myFunction("Li","Cherry");

new myFunction{
    var obj = {};
    obj.__proto__ = myFunction.prototype;
    var result = myFunction.call(obj,"Li","Cherry");
    return typeof result === 'obj'? result : obj;
}
  • 1.创建一个空对象 obj;开辟一个新的内存空间
  • 2.将新创建的空对象的隐式原型指向其构造函数的显示原型。
  • 3.使用 call 改变 this 的指向,指向新开辟的内存空间
  • 4.如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
所以我们可以看到,在 new 的过程中,我们是使用 call 改变了 this 的指向。

运用场景

    // 实现继承
    function Animal(name) {
        this.name = name;
        this.showName = function () {
            console.log(this.name);
        }
    }
    function Cat(name) {
        Animal.call(this, name);
    }
    var cat = new Cat('black cat');

    console.dir(Cat)

    cat.showName();

    // 数组追加
    var array1 = [1, 2, 3, 4, 5];
    var array2 = ['ss','dd','adf','iu'];
    // 在谁的基础上进行增加
    Array.prototype.push.apply(array2,array1);
    console.log(array2);
    
    //获取数组中的最大值和最小值
    var num = [1,2,4,5,6,7,9];
    var maxNum = Math.max.apply(Math,num);
    var minNum = Math.min.apply(Math,num);
    
    console.log(maxNum);
    console.log(minNum);
    
    // 将伪数组转为数组
    var fakeArr = {0:'a',1:'b',2:'c',length:2};
    var arr1 = Array.prototype.slice.call(fakeArr);
    console.log(arr1[0]);
    var arr2 = [].slice.call(fakeArr);
    console.log(arr2[0]);
    arr1.push('c');
    console.log(arr1);

    //保存this变量
    var foo = {
        bar:1,
        eventBind:function () {
            var _this = this;
            $('.someClass').on('click',function (event) {
                console.log(_this.bar);
            });
        }
    }

    var foo = {
        bar:1,
        eventBind:function () {
            $('.someClass').on('click',function (event) {
                console.log(this.bar);
            }.bind(this))
        }
    }

总结 apply 、 call 、bind

  • 三者都是用来改变函数的this对象的指向的;

  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;

  • apply 、 call 、bind 三者都可以利用后续参数传参;

  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。
    参考网站

  • this、apply、call、bind

  • 深入浅出 妙用Javascript中apply、call、bind

你好,再this的那边,你讲的是apply讲this指向新对象,这边说的是call呢

你好,再this的那边,你讲的是apply讲this指向新对象,这边说的是call呢

call和apply都可以改变this的指向,call改变this指向传入的是字符串对象,而apply传入的是数组对象☺️

所以在new那边,改变this指向,两个方法都是可以的吗

所以在new那边,改变this指向,两个方法都是可以的吗

对是的,apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。本质上是改变this的指向,只不过区别在于传入的参数列表存在差别,如果传入的参数都不是数组,那么这两个方法是一样的效果。你可以尝试着用实例代码跑一遍。

噢噢,知道了,非常感谢

噢噢,知道了,非常感谢

不客气😄加油🚀