关于bind(..) polyfill 代码的理解
你不知道的JavaScript(上卷)p93
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
/*
尽管代码部分仍未看懂,但应该还是有一点理解了
*/
// 判断是否有bind方法,没有就执行添加
// 如果想在浏览器运行这个方法,可以将这个判断!Function.prototype.bind直接改成true
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) { // oThis在本例中就是obj
// 做的事:判断调用bind方法的对象是不是一个函数function,若不是则报错
// 也就是说此方法只能是函数调用吗?这部分没太理解为什么要这样做
if (typeof this !== "function") {
// 与 ECMAScript 5 最接近的
// 内部 IsCallable 函数
throw new TypeError( "Function.prototype.bind - what is trying " + "to be bound is not callable" );
}
// Array.prototype.slice.call将类数组转换为数组,同时剔除了传入的第一个参数,即对象,而如果除了对象,还传入了其他参数,则参数会保留
// 把除了第一个参数(第一个参数用于绑定 this) 之外的其他参数都传给下层的函数(这种技术称为“部分应用”, 是“柯里化” 的一种)
var aArgs = Array.prototype.slice.call( arguments, 1 ),
fToBind = this, // 本例中this就是foo
fNOP = function(){},
fBound = function(){
return fToBind.apply(
// 如果this的原型链上有fNOP并且oThis转换为布尔值是true才用本来指向的this,否则将它转成oThis
// 这里就是判断是否要修改绑定的对象了
// 这里我的理解是如果this instanceof fNOP并且oThis不是undefined或null等,就认为开发者是特意这样设置的,按照开发者的意愿绑定对象,即使用oThis
// 但是this instanceof fNOP 这句又是什么意思呢
// this 的原型链上有fNOP的原型才会是true,什么情况下它会是true呢?
// 我认为这里是为了保持绑定的优先级(p94页)
// 优先级: new > 显示绑定 > 隐式绑定 > 默认绑定
// 原文说:这段代码会判断硬绑定函数是否是被 new 调用, 如果是的话就会使用新创建的 this 替换硬绑定的 this。
// 回忆一下,fBound的原型是fNOP构造的对象,那么当fBound作为构造函数,也就是说new调用时this指向的就是fNOP构造的对象,此时this 的原型链上有fNOP的原型,此时会返回true
// 这里需要补充一点:如果传入的是null/undefined,oThis就是null/undefined,但是由于如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、 apply 或者 bind, 这些值在调用时会被忽略, 实际应用的是默认绑定规则(原文p96)
// 也就是说如果传入null/undefined等值,最后还是会用默认绑定。
// 否则显式调用都会生效
(this instanceof fNOP && oThis ? this : oThis ),
// 将之前的参数和新传入的参数拼接起来
aArgs.concat( Array.prototype.slice.call( arguments ) )
);
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
};
function foo(num){
this.a = num;
}
var obj={};
var tmp =foo.bind(obj);
tmp(2);
console.log(obj.a); // 2
var tmp2 = new tmp(3);
console.log(tmp2.a); //3
</script>
</body>
</html>