为什么它在自己的空间里运作?

问题描述 投票:0回答:1
function Member(){
  this.x="hello";
};
var test = new Member();
Member.prototype.x = "test";
console.log(test.x);
//hello

我最初这样写是为了使构造函数期望其输出为“test”。但没有成功,结果是“你好”。 但是当我将构造函数设置为下面的构造函数时,它起作用了。

function Member(){
  Member.x="hello";
};

我想知道它是如何运作的。谢谢。

javascript constructor prototype
1个回答
1
投票

当您执行

new Member()
时,会发生一些事情,MDN 很好地描述了这些步骤:

  1. 创建一个空白的、纯 JavaScript 对象。为了方便起见,我们称之为

    newInstance

  2. 如果原型是
  3. newInstance

    ,则
    prototype
     的 [[Prototype]] 指向构造函数的 
    Object
    属性。否则,
    newInstance
    保持为普通对象,并以
    Object.prototype
    作为其 [[原型]]。 ...

  4. 使用给定参数执行构造函数,将

    newInstance
    绑定为
    this
    上下文(即所有对 构造函数中的
    this
    现在指的是
    newInstance
    )。

  5. 如果构造函数返回一个非原始,则该返回值将成为整个

    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()
由于性能原因仍应谨慎使用)

© www.soinside.com 2019 - 2024. All rights reserved.