之前面阿里的时候,面试官小哥哥问JS,第一个问题就是怎么用原生JS去实现bind()函数(内心emmmmmmmm,后面的面试结果大家也就可想而知了)
这篇博客算是事后的补习笔记吧。(学习中,B数还是有的,欢迎暴躁老哥喷我XD)
1、ES5版bind()原生JS实现:
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
// 判断是否在函数上调用
if (typeof this != "function") {
throw new TypeError("...");
}
// 获取传入值中的参数,存成数组
var aArgs = Array.prototype.slice.call(arguments, 1);
// 获取传入的函数
var fToBind = this;
// 定义一个函数对象,用于中转和保护原函数的原型
var fNOP = function() {};
// 这里就是关键思想了!
// bind执行完,返回的是一个函数!
// 下面是这个函数的字面量
var fBound = function() {
return fToBind.apply(
(
// 在《你不知道的JavaScript》书中,这部分代码没有详细解释
// 可以简单做如下理解
// 判断对象是被普通调用还是被new调用
// 被new调用时,需要修改硬绑定函数的this指向
this instanceof fNOP && oThis ?
this : oThis
),
aArgs.concat(Array.prototype.slice.call(arguments))
);
};
// 这里使用fNOP的实例来进行原型链中转,目的是为了保护原函数的原型
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP;
// 调用结束,返回的是函数!
return fBound
}
};
2、ES6版
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis, ...parm) {
if (typeof this != "function") {
throw new TypeError("...");
}
let fToBind = this;
let fNOP = function() {};
let fBound = function(...args) {
return Reflect.apply(fToBind, (
this instanceof fNOP && oThis ?
this : oThis
), parm.concat(args))
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP;
// 本代码未经过代码测试,各位看官谨慎食用
return fBound;
}
};