开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第十三天,点击查看活动详情
题引:
在我们日常的开发中,我们都会经常使用this这个关键字,该关键字关联了当下的作用域。但随着日常业务的开发,我们有时候会丢失对this的追踪,就需要确保this的指向是正确的,就会使用像apply、call、bind进行显示绑定,今天我们将主要来实现它们内部的实现。
正文:
其实它们三者是很相似的,实现一个就可以举一反三。 我们首先实现apply
apply方法第一个参数为this指向,第二个参数为数组
Function.prototype.myApply = function (thisArg, argArray) {
//1.判断this是不是函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
//1.获取要执行的函数
var fn = this;
//2.获取需要改变的this指向
thisArg =(thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window;
//3.执行改变后的this的函数
thisArg.fn = fn;
//4.判断是不是传参
argArray ? thisArg.fn(...argArray) : thisArg.fn();
delete thisArg.fn;
};
function foo(a, b) {
console.log("我被调用了", this, a, b);
}
foo.myApply(123, [1, 2]);
function bar(n) {
console.log("我被调用", n);
}
bar.myApply(123, [1]);
function bar1() {
console.log("我被调用");
}
bar1.myApply(123);
call跟apply极其相像,只在参数判断有所不同
Function.prototype.myApply = function (thisArg, ...args) {
//1.判断this是不是函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
//1.获取要执行的函数
var fn = this;
//2.获取需要改变的this指向
thisArg =(thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window;
//3.执行改变后的this的函数
thisArg.fn = fn;
//4.不管有没有传参都解构
thisArg.fn(...args)
delete thisArg.fn;
};
function foo(a, b) {
console.log("我被调用了", this, a, b);
}
foo.myApply(123, [1, 2]);
function bar(n) {
console.log("我被调用", n);
}
bar.myApply(123, [1]);
function bar1() {
console.log("我被调用");
}
bar1.myApply(123);
bind的方法跟call的参数方式是一样的,区别在于bind返回一个函数变量
Function.prototype.myBind = function(thisArg,...args1){
//1.判断this是不是函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
thisArg =thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
thisArg.fn = this
//区别在这,这里要使用闭包返回一个函数,该函数会执行已经指定好this的函数。
return function(...args2){
thisArg.fn(...args1,...args2)
delete thisArg.fn
}
}
function foo(a, b, c, d) {
console.log("我被调用了", this, a, b, c, d);
}
var result1 = foo.myBind(123, 1, 2, 3, 4);
result1();
var result2 = foo.myBind(123, 1);
result2(2, 3, 4);
以上就是三种显示绑定内部的实现。