Javascript 引用对象原型时显式指定_proto__与不指定有什么区别?

Javascript 引用对象原型时显式指定_proto__与不指定有什么区别?,javascript,Javascript,我试图理解JavaScript的内部结构。当谈到带有\uuuuu proto\uuuu的JavaScript原型继承时,我知道JavaScript中的每个对象,即函数、数组、对象文本等,都包含\uuuu proto\uuuuu属性,用于引用原型(这里的prototype指的是可以引用其他对象的功能,而不是函数构造函数的prototype属性)这些对象的。例如,假设我有一个名为myObject的对象,它几乎没有属性和成员 var myObject = { firstName:"Kishore

我试图理解JavaScript的内部结构。当谈到带有
\uuuuu proto\uuuu
的JavaScript原型继承时,我知道JavaScript中的每个对象,即函数、数组、对象文本等,都包含
\uuuu proto\uuuuu
属性,用于引用原型(这里的prototype指的是可以引用其他对象的功能,而不是函数构造函数的prototype属性)这些对象的。例如,假设我有一个名为myObject的对象,它几乎没有属性和成员

var myObject = {
   firstName:"Kishore",
   lastName:"Kumar",
   fullName: function() {
      console.log(this.firstName+" "+this.lastName);
   }
}
我想在下面的对象中继承fullName方法,即

var anotherObj = {
   firstName:"Anil"
}
所以我做了这个

anotherObj.__proto__ = myObject;
因此,我从上面的代码片段中了解到,anotherObj的原型现在引用myObject的全名的同一个内存点,并且可以访问它。因此我可以使用
anotherObj.\uu proto\uuuuUj.fullName()
。但是一些参考资料说,我可以直接这样做,即
anotherObj.fullName()
,我可以。JavaScript引擎在内部负责,并通过使用原型链提供全名

但现在,让我困惑的是,当我试图改变另一个对象的原型所指对象的属性,即myObject的属性时,我遇到了两个奇怪的问题

1) 当我做另一件事时,我希望另一个OtherObj的原型指向的myObject应该更改它的姓氏。但事实并非如此

2) 当我做另一件事时,它会改变

通过上述两种通过原型继承指向myObject的方法,我可以看出它们是不同的。我想知道为什么?显式使用
\uuuuu proto\uuuuu>与不使用来访问和修改另一个对象中myObject的成员有什么区别

注意:我理解使用
\uuuu proto\uuuu
会降低性能,我们不应该在开发中使用它。我问的问题是为了理解

编辑:为了更好地理解我的问题,下面我放了两段代码片段,我想知道它们的区别

代码1:

var myObject = {
   firstName:"Kishore",
   lastName:"Kumar",
   fullName: function() {
      console.log(this.firstName+" "+this.lastName);
   }
}

var anotherObj = {
   firstName:"Anil"
}

anotherObj.__proto__ = myObject;
anotherObj.lastName = "Korada";
console.log(anotherObj.__proto__);
var myObject = {
   firstName:"Kishore",
   lastName:"Kumar",
   fullName: function() {
      console.log(this.firstName+" "+this.lastName);
   }
}

var anotherObj = {
   firstName:"Anil"
}

anotherObj.__proto__ = myObject;
anotherObj.__proto__.lastName = "Korada";
console.log(anotherObj.__proto__);
输出:

代码2:

var myObject = {
   firstName:"Kishore",
   lastName:"Kumar",
   fullName: function() {
      console.log(this.firstName+" "+this.lastName);
   }
}

var anotherObj = {
   firstName:"Anil"
}

anotherObj.__proto__ = myObject;
anotherObj.lastName = "Korada";
console.log(anotherObj.__proto__);
var myObject = {
   firstName:"Kishore",
   lastName:"Kumar",
   fullName: function() {
      console.log(this.firstName+" "+this.lastName);
   }
}

var anotherObj = {
   firstName:"Anil"
}

anotherObj.__proto__ = myObject;
anotherObj.__proto__.lastName = "Korada";
console.log(anotherObj.__proto__);
输出:

您可以在上面两个代码片段输出中看到,当我尝试使用anotherObj时,lastName起作用


我只是想知道为什么?

您的问题与JavaScript的原型模型以及原型链接的概念有关

简而言之,这一概念可以概括为:

每个对象都有一个私有属性(称为[[Prototype]]),该属性保存到另一个称为其Prototype的对象的链接。该原型对象有自己的原型,依此类推,直到对象以null作为原型。根据定义,null没有原型,并充当此原型链中的最后一个链接

所以你可以把事情看成一条链子。在您的案例中,对于代码1和代码2,您所设置的链如下所示:

anotherObj --> myObject --> null
这也可以看作是:

{firstName: "Anil"} --> {firstName: "Kishore", lastName: "Kumar", fullName: function} --> null     
因此,当您尝试访问属性时,它将沿着原型链移动,从您访问它的点开始。在代码1中,您从另一个对象访问了
lastName
属性,使之成为“入口点”。由于
anotherObj
具有
lastName
属性,因此已找到该属性,并将在执行
anotherObj.lastName=“Korada”操作时直接修改该属性。当发现并修改属性时,搜索将停止

同时,对于代码2,在执行另一个对象时,您从原型对象访问了
lastName
属性,即
myObject
。这意味着搜索从那里开始,当属性
lastName
首先在
myObject
中找到时,
myObject
中的
lastName
属性将被修改为新值

当您从
anotherObj
中“输入”链时,可以直接引用
myObject
中的
fullName()
函数的原因是
anotherObj
没有此函数,因此搜索将继续沿着链向上,并在
myObject
中找到


我希望我的解释是正确的(如果有什么不对劲,一定要指出!)。另外,请随意参考下面这样一个有用的链接:

仅读取原型链后面的属性。修改属性只会影响直接对象,而不会影响其他对象。在理解原型继承时,请忽略已弃用的
\uuuuu proto\uuuu
!改为使用
Object.getPrototypeOf
/
Object.setPrototypeOf
。“所以我做了这个
jane.\uuuu proto\uuuuu=anotherObj;
”-你确定吗?正文的其余部分以另一种方式提及它们round@Bergi这是命名冲突。最初的例子实际上是简。但我在这里用过anotherObj@Bergi我知道它已被弃用,我不应该使用它。但从概念上讲,我想理解,当引用其他对象的原型时,使用或不使用proto有什么区别