function Person(arg) {
if (this.name == undefined) this.name = arg ? arg : "tom";
console.log("Name: " + this.name);
}
Person.prototype.setName = function(value) {
this.name = value;
};
Person.prototype.getName = function() {
return this.name;
};
var myobj = {name : "james"};
var new_func = Person.bind(myobj);
new_func(); // Name: james
var obj = new new_func(); // Name: tom
console.log(obj.getName()); // tom

有没有人可以解释为什么最后两个代码显示我" tom"而不是" james"?
在我的想法中,new_func将myobj绑定到Person构造函数,因此obj Object应该是Person的一个实例,并且它应该绑定到myobj。但它看起来完全不同。
答案 0 :(得分:1)
让我们分析一下代码。
var myobj = {name : "james"};
var new_func = Person.bind(myobj);
new_func(); // Name: james
var obj = new new_func(); // Name: tom
console.log(obj.getName()); // tom
首先声明一个对象文字,其中有一个密钥,您打算将其用作未来新 Person 的属性。
接下来,您将new_func
分配给 Person 和 myObj 的绑定。
这样,构造函数Person
被绑定到对象文字。但是,您正在使用该函数体创建一个新函数。当然你可以调用它,但不会创建任何新对象。
如果您只想提供 Person , name ,最好选择通过构造函数参数来完成。
function Person (name) {
this.name = name;
}
使用新的
调用它var p1 = new Person("James");
console.log(p1.name);
但是,如果要创建另一个的现有对象实例,则应使用Object.create([...].prototype)
。
var myobj = Object.create(Person.prototype);
var myobj.name = "james";
console.log(myobj instanceof Person);
答案 1 :(得分:1)
如果我们检查polyfill是否为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
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
在代码中我们可以看到apply是基于以下条件使用对象调用的
this instanceof fNOP ? this : oThis
,其中oThis
在我们的案例中为myobj
,并且创建了fNOP
以通过bind为新创建的方法创建原型链接。因此,当我们使用new operator new new_func()
时,这将是fNOP的一个基准。因此,当前对象将是this
而不是myobj
。
答案 2 :(得分:0)
在您使用bind
的情况下,您正在使用Person
的相同函数体创建一个新的绑定函数。
但当您调用它来创建new
Person
实例时,您没有传递任何参数,因此它将使用默认参数{{1创建一个新元素名字。
您可以从bind()文档中读取:
bind()函数创建一个新函数(一个绑定函数),它具有相同的函数体(ECMAScript 5术语中的内部调用属性),因为它被调用的函数(绑定函数的目标函数)具有此值绑定到bind()的第一个参数,它不能被覆盖。 bind()还接受在调用绑定函数时提供给目标函数的前导默认参数。
在以下说明中:
<强> 1)强>
Tom
您使用new_func();
作为此参考号召唤new_func()
。
<强> 2)强>
myobj
使用默认参数var obj = new new_func();
创建一个实例。
<强>解决方案:强>
obj.name = "Tom"
答案 3 :(得分:0)
为什么最后两个代码显示“汤姆”而不是“詹姆斯”?
因为bind
确实返回“绑定函数”,这在[[call]] ed时不同,但不会改变[[construct]]离子的行为。 bind
构造函数是不可能的,new
将始终创建一个新实例并忽略绑定值。
你不应该在构造函数上使用bind
,它适用于方法。为了进一步说明会发生什么,请参阅此示例:
function Person(arg) {
console.log("uninitialised", this);
this.name = arg;
}
var o = {name: "james"};
var bound = Person.bind(o);
var x = new bound("frank"); // uninitialised Person {}
console.log(x); // Person {name: frank}
console.log(o); // Object {name: james}
var x = bound("frank"); // uninitialised Object {name: james}
console.log(x); // undefined
console.log(o); // Object {name: frank}
答案 4 :(得分:-1)