call,apply,bind
作用
javaScript 权威指南上的解释是: call() 、apply()可以看作是某个对象的方法,通过调用方法的形式来间接调用函数。bind() 就是将某个函数绑定到某个对象上。
理解: call
、 apply
、bind
的作用是改变函数运行时 this 的指向
call
call 方法第一个参数是要绑定给 this 的值,后面传入的是一个参数列表。当第一个参数为 null、undefined 的时候,默认指向 window。
函数.call(指向新对象,参数 1,参数 2,....)
var arr = [1, 2, 3, 89, 46];
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4]); //89
var obj = {
message: "My name is: "
};
function getName(firstName, lastName) {
console.log(this.message + firstName + " " + lastName);
}
getName.call(obj, "Dot", "Dolby");
apply
apply 接受两个参数,第一个参数是要绑定给 this 的值,第二个参数是一个参数数组。当第一个参数为 null、undefined 的时候,默认指向 window。
var arr = [1, 2, 3, 89, 46];
var max = Math.max.apply(null, arr); //89
var obj = {
message: "My name is: "
};
function getName(firstName, lastName) {
console.log(this.message + firstName + " " + lastName);
}
getName.apply(obj, ["Dot", "Dolby"]); // My name is: Dot Dolby
obj 是作为函数上下文的对象,函数 getName 中 this 指向了 obj 这个对象。参数 firstName 和 lastName 是放在数组中传入 getName 函数。
bind
和 call 很相似,第一个参数是 this 的指向,从第二个参数开始是接收的参数列表。区别在于 bind 方法返回值是函数以及 bind 接收的参数列表的使用。
- bind 将函数 this 绑定到对象上,返回新函数
- 这个新函数的 this 将不能被改变,只能指向绑定的对象
var obj = {
name: "Dot"
};
function printName() {
console.log(this.name);
}
var dot = printName.bind(obj);
console.log(dot); // function () { … }
dot(); // Dot
bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。
应用场景
求数组中的最大和最小值
var arr = [1, 2, 3, 89, 46];
var max = Math.max.apply(null, arr); //89
var min = Math.min.apply(null, arr); //1
将类数组转化为数组
var trueArr = Array.prototype.slice.call(arrayLike);
数组追加
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var total = [].push.apply(arr1, arr2); //6
// arr1 [1, 2, 3, 4, 5, 6]
// arr2 [4,5,6]
判断变量类型
function isArray(obj) {
return Object.prototype.toString.call(obj) == "[object Array]";
}
isArray([]); // true
isArray("dot"); // false
利用 call 和 apply 做继承
function Person(name, age) {
// 这里的this都指向实例
this.name = name;
this.age = age;
this.sayAge = function() {
console.log(this.age);
};
}
function Female() {
Person.apply(this, arguments); //将父元素所有方法在这里执行一遍就继承了
}
var dot = new Female("Dot", 2);
使用 log 代理 console.log
function log() {
console.log.apply(console, arguments);
}
// 当然也有更方便的 var log = console.log()
总结
call、apply 和 bind 函数存在的区别:
bind 返回对应函数, 便于稍后调用; apply, call 则是立即调用。
除此外, 在 ES6 的箭头函数下, call 和 apply 将失效, 对于箭头函数来说:
- 箭头函数体内的 this 对象, 就是定义时所在的对象, 而不是使用时所在的对象;所以不需要类似于
var _this = this
这种写法 - 箭头函数不可以当作构造函数,也就是说不可以使用 new 命令, 否则会抛出一个错误
- 箭头函数不可以使用 arguments 对象,,该对象在函数体内不存在. 如果要用, 可以用 Rest 参数代替