js中call、apply和bind主要用于改变调用函数(或方法)中this的指向
区别:
- call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
- bind()方法的用法和call()方法类似,区别就是bind()不会立即执行,可二次传参后再执行。
一、call、apply和bind的介绍
(1) Function.prototype.call()
call() 方法使用一个指定的 this 值和参数来调用一个函数。
语法:function.call(thisArg, arg1, arg2, ...)
参数:
thisArg: 在 function 函数运行时使用的 this 值。非严格模式下,若指定为 null 或 undefined 时会自动替换为指向全局对象。
arg1, arg2, …: 指定的参数列表。
应用举例:
var obj1 = {name: 'js1', fn: function() {return this.name}}
var obj2 = {name:'js2'}
console.log(obj1.fn()); //js1
console.log(obj1.fn.call(obj2)); //js2
//当一个object没有某个方法,但是其他的有,可以借助call或apply用其它对象的方法来操作
(2) Function.prototype.apply()
方法调用一个具有给定 this值的函数,以及作为一个数组(或类似数组对象)提供的参数。
语法:func.apply(thisArg, [arg1,arg2,...])
应用举例:
var obj1 = {name: 'js1', fn: function() {return this.name}}
var obj2 = {name:'js2'}
console.log(obj1.fn()); //js1
console.log(obj1.fn.apply(obj2)); //js2
(3) Function.prototype.bind()
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
语法:function.bind(thisArg, arg1, arg2, ...)
应用举例:
var obj1 = {name: 'js1', fn: function() {return this.name}}
var obj2 = {name:'js2'}
console.log(obj1.fn()); //js1
console.log(obj1.fn.bind(obj2)); //fn
console.log(obj1.fn.bind(obj2)()); //js2
二、call、apply和bind的实现
call的内部实现
//call的内部实现
Function.prototype.call = function(context) {
let cxt = context || window;
cxt.func = this;
//获取实参
let args = Array.from(arguments).slice(1);
let res = arguments.length > 1 ? cxt.func(...args) : cxt.func();
delete cxt.func;
return res;
}
//arguments:接受所有实参的伪数组
apply的内部实现
//apply的内部实现
Function.prototype.apply = function(context) {
let cxt = context || window;
cxt.func = this;
let res = arguments[1].length > 0 ? cxt.func(...arguments[1]) : cxt.func();
delete cxt.func;
return res;
}
bind内部实现
//bind内部实现
Function.prototype.bind = function(context) {
let cxt = JSON.parse(JSON.stringify(connext)) || window;//深拷贝
cxt.func = this;
//获取实参
let args = Array.from(arguments).slice(1);
//返回函数
return function() { //没有立即执行的核心
let allArgs = args.concat(Array.from(arguments));
return allArgs.length > 0 ? cxt.func(...allArgs) : cxt.func();
}
}