bind-call-apply-用法与区别

3次阅读

共计 2526 个字符,预计需要花费 7 分钟才能阅读完成。

1、bind call apply 方法的来源

 这三个方法继承自 Function.prototype 中,属于实例方法。
Function.prototype.hasOwnProperty('call');
Function.prototype.hasOwnProperty('apply');
Function.prototype.hasOwnProperty('bind');
 全部返回 true,验证。

2、Function.prototype.call(),call 方法可以指定该函数内部的 this 的指向,然后在所指定的作用域中,调用该函数,并且会立即执行该函数。

var obj = {name: '小明'};
var name = '小花';
function sayHello(){console.log('大家好,我叫' + this.name);
}

sayHello(); // 大家好,我叫小花
sayHello.call(); // 大家好,我叫小花
sayHello.call(this); // 大家好,我叫小花

sayHello.call(null); // 大家好,我叫小花
sayHello.call(undefined); // 大家好,我叫小花

sayHello.call(obj); // 大家好,我叫小明

上面的代码中,sayHello 函数中的 this 关键字,如果指向全局对象,返回结果是“大家好,我是小花”。另外,如果 call 方法没有参数,或者参数是 this、null 或者是 undefined,则等同于指向全局对象。如果使用 call 方法将 this 关键字指向 obj 对象,也就是该函数执行时所在的作用域为 obj 对象,返回结果是“大家好,我是小明”。

var obj = {name: '小明'};
var name = '小花';
function calc(a,b){console.log(this.name + '的年龄是' + a*b);
}

calc(1,5);
calc.call(null,1,5);
calc.call(obj,1,6);

call() 方法可以传递两个参数。第一个参数是指定函数内部中 this 的指向(也就是函数执行时所在的作用域),第二个参数是函数调用时需要传递的参数。第一个参数是必须的,可以是 null,defined,this, 但是不能为空。第二个参数中必须一个个添加,而在 apply 中必须以数组的形式添加。

3、Function.prototype.apply(),apply 方法的作用与 call 方法类似,也是改变 this 指向(函数执行时所在的作用域),然后在指定的区域中调用该函数。同时也是立刻执行该函数,唯一的区别就是,他接收一个数组作为执行时的参数。apply 方法的第一个参数也是 this 所要指向的那个对象,如果设为 null 或者 undefined 或者 this,则等同于指向全局对象,第二个参数是一个数组,该数组的所有元素依次作为参数,在调用时传入原函数。原函数的参数,call 方法必须一个一个添加。以下是使用方法以及常用情景。

function calc(a, b) {console.log(a + b);
}

calc.call(null, 2, 3); //5
calc.apply(null, [2, 3]); //5

// 找出数组中最大值
var arr = [2, 4, 5, 7, 8, 10];
console.log(Math.max.apply(null, arr)); //10
console.log(Math.max.call(null,2, 4, 5, 7, 8, 10)); //10

// 将数组中的空元素变为 undefined, 通过 apply 方法,利用 Array 构造函数将数组中的空元素变成 undefinde, 空元素与 undefined 的差别在于 forEach 方法会跳过空元素,因此遍历内部元素时会得到不同的结果
console.log(Array.apply(null, [1, , 3])); // [1,undefined, 3]

4、Function.prototype.bind(),bind 方法用于指定函数内部的 this 指向 ( 执行时所在的定义域),然后返回一个函数。bind 方法不会立即执行一个函数。

var calc = {
    a: 1,
    count: function() {console.log(this.a++);
    }
};

calc.count(); //1
calc.count(); //2
calc.count(); //3

上面代码中,this.a 指向 calc 对象内部的 a 属性,如果这个方法赋值给另外一个变量,调用时就会出错。

var calc = {
    a: 1,
    count: function() {console.log(this.a++);
    }
};

var f = calc.count;
f(); //NaN

上述代码中,如果把 conut 方法赋值给 f 变量,那么 this 对象的指向就不再是 calc 对象了,而是 window 对象。而 window.a 默认为 undefined,进行递增计算之后 undefined++ 就等于 NaN。
为了解决这个问题,可以使用 bind 方法,将 calc 对象里的 this 绑定到 calc 对象上,或者直接调用。

var f = calc.count.bind(calc);
f(); //1
f(); //2
f(); //3
calc.count.bind(calc)() //1
calc.count.bind(calc)() //2
calc.count.bind(calc)() //3

当然 this 也可以绑定到其他对象上。

var obj = {a: 100};
var f = calc.count.bind(obj);
f(); //100
f(); //101
f(); //102

同样,我们也可以给 bind 方法传递参数,第一个参数如果为 undefined、null 或者 this,会将函数内部的 this 对象指向全局环境,第二个为调用时需要的参数,并且传递参数的形式与 call 方法相同。

上面代码中,可以看出 call、apply、bind 三者的区别:call 和 apply 方法都是在调用之后立即执行。而 bind 调用之后是返回原函数,需要再调用一次才行。

参考链接:https://www.cnblogs.com/Jade-…

正文完
 0