vik*_*ant 14 javascript new-operator
这是一个纯粹的理论问题.我从'你不知道js'学习javascript,我被困bind在JS 中的函数实现.考虑以下代码:
function foo(something) {
this.a = something;
}
var obj1 = {};
var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2
var baz = new bar(3);
console.log(obj1.a); // 2
console.log(baz.a); // 3Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我们绑定foo()到obj1,所以this在foo()属于obj1这就是为什么obj1.a变成2当我们调用bar(2).但是new操作员能够优先使用,obj1.a即使bar(3)被调用也不会改变new.
以下是MDN页面提供的polyfill bind(..):
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError( "Function.prototype.bind - what " +
"is trying to be bound is not callable"
);
}
var aArgs = Array.prototype.slice.call( arguments, 1 ),
fToBind = this,
fNOP = function(){},
fBound = function(){
return fToBind.apply(
(
this instanceof fNOP &&
oThis ? this : oThis
),
aArgs.concat( Array.prototype.slice.call( arguments ) )
);
}
;
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
Run Code Online (Sandbox Code Playgroud)
根据这本书允许新覆盖的部分是:
this instanceof fNOP &&
oThis ? this : oThis
// ... and:
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
Run Code Online (Sandbox Code Playgroud)
所以,现在的重点.根据这本书:"我们实际上不会深入解释这种技巧是如何工作的(它复杂并且超出了我们的范围),但实际上该实用程序确定是否使用new调用了硬绑定函数(导致新构造的对象就是它的这个),如果是这样的话,它会使用新创建的对象,而不是先前为此指定的硬绑定."
bind()函数中的逻辑如何允许new操作符覆盖硬绑定?
首先,了解对象的原型([[Prototype]]通过函数Object.getPrototypeOf或不推荐的__proto__属性表示规范和可访问的)与名称为的函数的属性之间的区别非常重要prototype.每个函数都有一个名为的属性prototype,在调用函数时使用new.
当您调用函数时new,该函数提供的this值设置为新构造的对象,其原型(即[[Prototype]])设置为prototype被调用函数的属性.也就是说,当你调用时new Foo(),那么当Foo运行代码时,该this值将是表单的对象
{ [[Prototype]]: Foo.prototype }
Run Code Online (Sandbox Code Playgroud)
让我们简要地讨论一下变量:
fToBind是绑定的函数:for foo.bind(...),foois fToBind.fBound是绑定版本fToBind; 它是操作的返回值bind.fBound充当原始fToBind函数的守门员,并决定调用它时获得的this值fToBind.oThis是提供给的第一个参数bind,即绑定到函数的对象this.fNOP是一个prototype属性设置为的函数fToBind.prototypefBound.prototype = new fNOP() 导致这些是真的:
Object.getPrototypeOf(fBound.prototype) === fNOP.prototype
Object.getPrototypeOf(fBound.prototype) === fToBind.prototype
Run Code Online (Sandbox Code Playgroud)当fBound调用时new,则this提供给fBound表单的那个
{ [[Prototype]]: fBound.prototype }
Run Code Online (Sandbox Code Playgroud)
并且fBound.prototype是表单的对象
{ [[Prototype]]: fNOP.prototype }
Run Code Online (Sandbox Code Playgroud)
制作this相当于的完整形式
{ [[Prototype]]: { [[Prototype]]: fNOP.prototype } }
Run Code Online (Sandbox Code Playgroud)
因此,fNOP.prototype在调用this时,是在新创建的对象的原型链中.这正是操作测试的内容:fBoundnewobject instanceof constructor
所述
instanceof操作者测试的存在constructor.prototype在object的原型链.
&&这里和三元之间的操作顺序是:
(this instanceof fNOP && oThis) ? this : oThis
Run Code Online (Sandbox Code Playgroud)
如果this具有fNOP.prototype在其原型链和原始bind呼叫被赋予结合的功能的truthy第一个参数,然后使用自然地创建this提供给fBound当它被调用new并提供该到fToBind的,而不是结合this.
| 归档时间: |
|
| 查看次数: |
661 次 |
| 最近记录: |