function Member(){
this.x="hello";
};
var test = new Member();
Member.prototype.x = "test";
console.log(test.x);
//hello
我最初这样写是为了使构造函数期望其输出为“test”。但没有成功,结果是“你好”。 但是当我将构造函数设置为下面的构造函数时,它起作用了。
function Member(){
Member.x="hello";
};
我想知道它是如何运作的。谢谢。
当您执行
new Member()
时,会发生一些事情,MDN 很好地描述了这些步骤:
- 如果原型是
创建一个空白的、纯 JavaScript 对象。为了方便起见,我们称之为
。newInstance
,则将
newInstance
prototype
的 [[Prototype]] 指向构造函数的Object
属性。否则,保持为普通对象,并以newInstance
作为其 [[原型]]。 ...Object.prototype
使用给定参数执行构造函数,将
绑定为newInstance
上下文(即所有对 构造函数中的this
现在指的是this
)。newInstance
如果构造函数返回一个非原始,则该返回值将成为整个
表达式的结果。 否则,如果构造函数不返回任何内容或 返回一个原语,而是返回new
。 (通常情况下 构造函数不返回值,但他们可以选择这样做 覆盖正常的对象创建过程。)newInstance
这意味着在你的例子中:
test
是使用 this
调用时在 Member
构造函数中创建的 new
对象(即:“实例”)。test
的[[原型]]1指向对象Member.prototype
。这意味着对象 Member.prototype
上的所有属性都可以通过 test
访问(如果不是在 test
上“隐藏”)当您使用
test.x
时,我们首先在 x
创建的实例上查找 new Member()
(即:在函数中创建并返回的 this
对象)。如果在实例本身上找不到 x
,则检查原型(存储在 __proto__
属性中的对象)是否有 x
(然后,如果在原型上找不到它,我们将检查原型的原型等等)。
在您的第一个示例中,由于我们能够在对象实例本身上找到
x
,其值为 "hello"
,因此它会记录 "hello"
并且不检查原型(实例“shadows”上的 x
) “原型上的 x
)。
在第二个示例中,由于您的函数没有向
this
添加任何属性,因此 new Member()
返回的实例没有像第一个示例那样具有 x
属性(它是一个空对象 {}
) ,因此我们检查原型(从上面的步骤 2 中我们看到的是 Member.prototype
),它确实有一个 x
属性设置为 "test"
,因此它会记录 "test"
。执行 Member.x
会将 x
作为属性添加到函数对象,但不会影响使用 new
创建的实例。
1 请注意,正如 RobG 指出的那样,
__proto__
的使用已已弃用。该规范在构造的对象实例上使用内部槽 [[Prototype]]
,并用于指向构造函数的 .prototype
属性。当您需要访问/设置 __proto__
槽的对象时,请避免使用 Object.getPrototypeOf()
,而是使用
Object.create()
、
Object.setPrototypeOf()
或
[[Prototype]]
等方法(尽管使用 setPrototypeOf()
由于性能原因仍应谨慎使用)