文章首发于掘金 call&apply&bind小结
一、方法定义
call方法
语法: call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义: 调用一个对象的一个方法,以另一个对象替换当前对象。
说明: call
方法可以用来代替另一个对象调用一个方法。call
方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 arg1 … argN为被调用方法的传参。
function numAdd( a, b ) {
console.log(this);
console.log(a + b, "123456");
}
function numPow( a, b ) {
console.log(this);
console.log(Math.pow(a, b), "xxxxxx")
}
//把numAdd方法放在numPow上执行
//this指向numPow
numAdd.call(numPow, 3, 4); // 7
//把numPow方法放在numAdd上执行
//this指向numAdd
numPow.call(numAdd, 3, 4); // 81
Object.prototype.toString.call(numAdd)
apply方法
语法: apply([thisObj[,argArray]])
定义: 应用某一对象的一个方法,用另一个对象替换当前对象。
说明: apply
的第一个参数thisObj和call
方法的一样,第二个参数argArray为一个传参数组。thisObj如果未传,那么 Global 对象被用作 thisObj。
function add( a, b ) {
console.log(this);
console.log(a + b, "123456");
}
function pow( a, b ) {
console.log(this);
console.log(Math.pow(a, b), "xxxxxx")
}
//把numAdd方法放在numPow上执行
//this指向pow
add.apply(pow, [ 3, 4 ]);; // 7
//把numPow方法放在numAdd上执行
//this指向add
pow.apply(add, [ 3, 4 ]); // 81
bind方法 ECMAScript5中扩展了叫bind的方法(IE6,7,8不支持)
语法: bind([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义: 应用某一对象的一个方法,用另一个对象替换当前对象。
说明: bind
的thisObj参数也和call方法一样,thisObj如果未传,那么 Global 对象被用作 thisObj。arg1 … argN可传可不传。如果不传,可以在调用的时候再传。如果传了,调用的时候则可以不传,调用的时候如果你还是传了,则不生效。
function add( a, b ) {
console.log(this);
console.log(a + b, "123456");
}
function pow( a, b ) {
console.log(this);
console.log(Math.pow(a, b), "xxxxxx")
}
//把add方法放在pow上执行
//this指向pow
aadd.bind(pow)( 3, 4); // 7
//把pow方法放在add上执行
//this指向add
pow.bind(add)( 3, 4); // 81
二、call,apply,bind的相似
都是用来改变函数
this
指向的第一个参数都是
this
要指向的对象都可以传参
三、call,apply,bind的区别
call
和apply
都是对函数的直接调用bind
返回的是一个函数,需要配合()进行调用call
和bind
的传参使用,分隔的 例如(item1,item2,item3...)apply
的传参使用数组[...arguments]
四、简单实现call
Function.prototype.selfCallWithEs5 = function (context) {
var context = context || window;
context.fn = this;
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push("arguments[" + i + "]");
}
args = args.join(",");
var result = eval("context.fn(" + args + ")");
delete context.fn;
return result; //因为有可能this函数会有返回值return
}
Function.prototype.selfCallWithEs6 = function (context, ...args) {
context = context || window;
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
};
五、简单实现apply
Function.prototype.selfApplyWithEs5 = function (context, arr) {
var context = context || window;
context.fn = this;
var args = [];
var params = arr || [];
for (var i = 0; i < params.length; i++) {
args.push("params[" + i + "]");
}
args = args.join(",");
var result = eval("context.fn(" + args + ")");
delete context.fn;
return result; //因为有可能this函数会有返回值return
}
Function.prototype.selfApplyWithEs6 = function(context, arr) {
context = context || window;
context.fn = this;
arr = arr || [];
const result = context.fn(...arr);
delete context.fn;
return result;
}
六、简单实现bind
Function.prototype.selfBindWithEs5 = function (context) {
var _this = this;
var argsParent = Array.prototype.slice.call(arguments, 1);
return function () {
var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组
_this.apply(context, args);
};
}
Function.prototype.selfBindWithEs6 = function (context) {
var fn = this;
var argsParent = [...arguments];
return function () {
fn.call(...argsParent, ...arguments);
};
}