apply()与call()方法详解

我们希望能够尽我们所能,来让这个世界变的更简单,如果你想了解我们,请点击这里


在JS的每个函数之中,都包含两个非集成而来的方法apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,等于设置函数体内this对象的值
两个方法唯一的区别是接受的参数不同appay()方法接受运行函数的作用域和数组,call()方法接受运行函数的作用域和直接调用函数的参数 看下面的例子

// 声明一个方法sum作为调用apply和call方法的函数
        function sum (a , b) {
            console.log(a + b);
        }

        // 调用apply方法传入一个数组
        function callSum1 (a, b) {
            sum.apply(this, [a, b]);
        }

        // 调用apply方法传入arguments对象,其实也是一个数组
        function callSum2 (a, b) {
            sum.apply(this, arguments);
        }

        // 调用call方法传入sum方法需要的参数 a, b
        function callSum3 (a, b) {
            sum.call(this, a,b);
        }

然后我们分表调用 callSum1 ,callSum2 ,callSum3这三个函数

callSum1(1, 1);
// 2
callSum2(1, 1);
// 2
callSum3(1, 1);
// 2

得到的打印结果相同。
我们来回顾一下apply和call方法的定义
在特定的作用域中调用函数,等同于

function callSum1 (a, b) {
    //sum.apply(this, [a, b]);
    console.log(a + b);
}

这样看或许不是很直观,让我们来看下面这个例子

// 定义一个全局变量name:javascript
        var name = 'javascript';

        // 定义一个对象android, 他的name为 android
        var android = {
            name: 'android'
        }

        // 定义一个方法ios, 他的name为 ios (在javascript中 function也是对象)
        var ios = function () {
            this.name = 'ios';
        }

        // 输出name的值
        function consoleName () {
            console.log(this.name);
        }

然后我们这样去调用它

 consoleName.call(window);   // javascript
 consoleName.call(this);   // javascript
 consoleName.call(android);     // android
 consoleName.call(ios);   // undefined

我们可以发现前三个调用都符合我们的预期,在特定的作用域内调用函数,等于改变了函数体内this对象的值 相当于我们把方法consoleName放到了指定的作用域中,然后在指定的作用域中调用了他,相当于如下代码。

consoleName.call(window);
 // window.consoleName = function () {
 //     console.log(this.n);
 // }
 //  window.consoleName();

 consoleName.call(this);
 // window.consoleName = function () {
 //     console.log(this.n);
 // }
 //  window.consoleName();

 consoleName.call(android);
//  var android = {
 //           n: 'android',
 //           consoleName: function () {
 //               console.log(this.n);
 //           }
 //       }
 // android.consoleName();

但是为什么再去调用 consoleName.call(ios);的时候会打印 undefined那?我们关注一下ios的定义

var ios = function () {
    this.n = 'ios';
}

consoleName.call(ios);
// var ios = function () {
//            this.n = 'ios';
//            consoleName: function () {
//                console.log(this.n);
//           }
//        }

看出来了吗? 我们等于给方法添加了一个属性,那对于ios这种我们应该怎么做那? 看一下修改之后的代码

// 标记Ios为一个构造函数
        var Ios = function () {
            this.n = 'ios';
        }
// 创建Ios对象,相当于我们在Ios的对象之中调用了consoleName方法,把consoleName的this指向了Ios的对象
 consoleName.call(new Ios());

打印结果 符合预期

猜你喜欢

转载自blog.csdn.net/u011068996/article/details/79897985