手写 bind、apply、call
手写 call
- call() :在使⽤⼀个指定的 this 值和若⼲个指定的参数值的前提下调⽤某个函数或⽅法。
思路
- 将函数设为对象的属性;
- 执⾏该函数;
- 删除该函数
javascript
Function.prototype.myCall = function (context, ...args) {
// 判断是否是undefined和null
if (typeof context === "undefined" || context === null) {
context = window;
}
let fnSymbol = Symbol();
context[fnSymbol] = this;
let fn = context[fnSymbol](...args);
delete context[fnSymbol];
return fn;
};
手写 apply
- apply 的实现跟 call 类似,只是⼊参不⼀样,apply 为数组
javascript
Function.prototype.myApply = function (context, args) {
// 判断是否是undefined和null
if (typeof context === "undefined" || context === null) {
context = window;
}
let fnSymbol = Symbol();
context[fnSymbol] = this;
let fn = context[fnSymbol](...args);
delete context[fnSymbol];
return fn;
};
手写 bind
- bind() ⽅法会创建⼀个新函数。
- 当这个新函数被调⽤时,bind() 的第⼀个参数将作为它运⾏时的 this,
- 之后的⼀序列参数将会在传递的实参前传⼊作为它的参数
bind 函数的特点:
- 返回⼀个函数;
- 可以传⼊参数;
- ⼀个绑定函数也能使⽤ new 操作符创建对象;当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传⼊的参数依然⽣效。
javascript
Function.prototype.myBind = function (context) {
if (typeof this !== "function") {
throw new Error(
"Function.prototype.bind - what is trying to be bound is not callable"
);
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
// 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来⾃绑定函数的值
// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
return self.apply(
this instanceof fNOP ? this : context,
args.concat(bindArgs)
);
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
极简版本
javascript
Function.prototype.myBind = function (context) {
// 判断是否是undefined 和 null
if (typeof context === "undefined" || context === null) {
context = window;
}
self = this;
return function (...args) {
return self.apply(context, args);
};
};