我试图了解原型和构造器是如何在JavaScript中工作的,并遇到了这种情况。
我总是想象在JavaScript中如何创建对象
return this返回。这种理解方式似乎无法解释obj2和obj3。
例如,我显式地将Foo.prototype.constructor设置为obj2的其他东西,但是obj2仍然拥有属性bar。假设bar存储在Foo的原型中,这解释了为什么obj2拥有属性bar,为什么obj3是由Object创建的,但是如果我再创建几个obj2,这意味着它们在Foo的原型上共享相同的变量bar,我认为情况并非如此。
有人能更合理地解释一下为什么obj2和obj3是这样的吗?
function Foo(){
this.bar = true;
}
console.log('obj1');
var obj1 = new Foo();
console.log(obj1);
console.log(obj1.constructor === Foo);
console.log('obj2');
Foo.prototype.constructor = 3; //a dummy value
var obj2 = new Foo();
console.log(obj2);
console.log(obj2.constructor === Foo);
function Bar(){
this.foo = true;
}
console.log('obj3');
Bar.prototype = 3;
var obj3 = new Bar();
console.log(obj3);
console.log(obj3.constructor === Bar);
console.log(obj3.constructor === Object);
发布于 2017-01-25 04:56:52
我昨天看到你的帖子了,但当时我有点忙,现在我有空了,我想回答你的问题。
执行代码new Foo()时,会发生以下情况:
new关键字调用的,因此它被视为构造函数,因此创建了一个空对象。Foo.prototype。this绑定到新创建的对象。this.bar = true被执行。new Foo等价于new Foo(),即如果未指定参数列表,则调用Foo时不带参数。假设bar存储在Foo的原型中,这就解释了为什么obj2有属性条,为什么obj3是由对象创建的,但是如果我再创建几个obj2s,这意味着它们在Foo的原型上共享相同的变量条,我认为情况并非如此。
你是正确的。
bar是obj1和obj2拥有的一个属性,例如:
console.log(obj1.hasOwnProperty("bar")); // true但是,如果添加这样的属性:
Foo.prototype.bar2 = true;
console.log(obj1.hasOwnProperty("bar2")); // falsebar2的值由所有Foo实例共享,但是bar属性不是由Foo实例共享的,每个Foo实例可以有自己的bar值。
有人能更合理地解释一下为什么obj2和obj3是这样的吗?
当您声明构造函数Foo时,Foo.prototype.constructor将自动指向Foo,console.log(Foo.prototype)将显示实际上这是循环引用,在递归遍历对象时应该检测到循环引用。但是在您的例子中,Foo.prototype.constructor = 3,幸运的是,new Foo()表达式的过程不涉及Foo.prototype.constructor属性,因此它将被正确地执行,但是obj2.constructor或Foo.prototype.constructor的值仍然是3。
Bar.prototype = 3,我的理论是,当new Bar()执行时,就像在步骤2中一样,创建的对象应该链接到Bar.prototype,但是由于Bar.prototype的值没有引用对象,所以隐式地分配了一个默认值,即Object.prototype。
console.log(Object.prototype === Object.getPrototypeOf(obj3)); // true由于object.prototype.constructor对Object的引用,obj3.constructor也引用了Object,但是obj3的实际构造函数仍然是Bar,因为步骤1也可以被console.log(obj3.foo); // true证明。
更多信息:How objects are created when the prototype of their constructor isn't an object?
发布于 2017-01-24 07:27:49
您的理解是几乎是正确的,但以下情况除外:
不,构造函数如下:
function Foo(){
this.bar = true;
}并且直接调用构造函数而不存在对象:
new Foo();
new Bar();那只是个函数调用。因为new这个关键字,它有点特别。因此,为了修改一下您的理解,我将对您的描述做一些修改:
new关键字调用的,所以它被视为构造函数。注意,在调用构造函数本身中创建构造函数时,对象根本不需要搜索构造函数。调用构造函数是第一步,而不是第三步。
请注意,这是对如何构造对象的非常高层次的描述。有几个细节,如如何对待this是被掩盖的。
发布于 2017-01-24 09:28:11
例如,我显式地将Foo.prototype.constructor设置为obj2的其他东西,但是obj2仍然拥有属性条。。。
在您的例子中,constructor只是Foo上的一个原型属性。它不是您所称的obj2的构造函数。obj2的构造函数是Foo。通过将名为constructor的属性应用于原型,您不会更改构造函数!
。。但假设bar存储在Foo的原型中,这就解释了为什么obj2有属性条。
与您的想法相反,bar不是存储在Foo的prototype中,它是存在于obj2实例上的一个属性,它是一个实例属性而不是一个原型属性。在您的示例中,原型属性是constructor。
为了更清晰起见,请看下面的例子:
function Foo() {
this.bar = true;
}
var obj = new Foo();
console.log('The instance property "bar" is ' + obj.bar);
Foo.prototype.baz = 4;
console.log('The prototype property "baz" is ' + obj.baz);
Foo.prototype.bar = 5;
console.log('The prototype property "bar"=' + Foo.prototype.bar + ' is overridden by instance property "bar"=' + obj.bar);
https://stackoverflow.com/questions/41822188
复制相似问题