bind/apply/call
bind/apply/call简介
bind()、apply()、call()都是Function对象原型上的方法,其作用是可以改变调用函数的this指向,虽然功能一样,但它们三个在用法上也有不同之处:
apply和call在被函数调用后可以直接运行该函数,而bind则返回改变了this指向后的函数,调用时可以继续传参apply是以数组的形式进行传参,而call和bind是以列表的形式进行传参,并且bind可以多次传入
手写bind/apply/call
bind
Function.prototype.myBind = function (context, ...args1) {
// bind并不会立即调用而是返回一个函数,并且可以多次传参
return (...args2) => {
// 如果改变的指向为null或undefined,则指向window
context = context || window;
// 将this指向的函数(即调用myBind函数的函数)赋值给context对象的一个属性
context.fn = this;
// 用context来调用该函数,那么该函数中的this则指向context
let result = context.fn(...args1, ...args2);
// 删除context中的fn属性
delete context.fn;
// 返回 result(即该箭头函数)
return result;
}
}
// 测试
let obj = {
name: "lzt"
}
function fn(a, b, c) {
console.log(this.name, a, b, c);
}
fn(1, 2, 3); // undefined 1 2 3
let newFn = fn.myBind(obj, 1, 2);
newFn(3); // lzt 1 2 3
apply
Function.prototype.myApply = function (context, args) {
// 如果改变的指向为null或undefined,则指向window
context = context || window;
// 将this指向的函数(即调用myApply函数的函数)赋值给context对象的一个属性
context.fn = this;
// 用context来调用该函数,那么该函数中的this则指向context
let result = context.fn(...args);
// 删除context中的fn属性
delete context.fn;
// 返回 result
return result;
}
// 测试
let obj = {
name: "lzt"
}
function fn(a, b, c) {
console.log(this.name, a, b, c);
}
fn(1, 2, 3); // undefined 1 2 3
fn.myApply(obj, [1, 2, 3]); // lzt 1 2 3
call
Function.prototype.myCall = function (context, ...args) {
// 如果改变的指向为null或undefined,则指向window
context = context || window;
// 将this指向的函数(即调用myCall函数的函数)赋值给context对象的一个属性
context.fn = this;
// 用context来调用该函数,那么该函数中的this则指向context
let result = context.fn(...args);
// 删除context中的fn属性
delete context.fn;
// 返回 result
return result;
}
// 测试
let obj = {
name: "lzt"
}
function fn(a, b, c) {
console.log(this.name, a, b, c);
}
fn(1, 2, 3); // undefined 1 2 3
fn.myCall(obj, 1, 2, 3); // lzt 1 2 3