gpt4 book ai didi

javascript - Javascript原型(prototype)继承和对象属性阴影

转载 作者:数据小太阳 更新时间:2023-10-29 04:02:35 24 4
gpt4 key购买 nike

var person = { name :"dummy", personal_details: { age : 22, country : "USA" } };

var bob = Object.create(person);

bob.name = "bob";
bob.personal_details.age = 23;


console.log(bob.personal_details === person.personal_details);
// true : since it does not shadow object of prototype object

console.log(bob.name === person.name);
// false : since it shadows name

////now
bob.personal_details = {a:1};
console.log(bob.personal_details === person.personal_details);

//假

当对象 bob 尝试覆盖 的“ 名称”属性时,它会在bob自身中被遮盖。

但是如果使用 personal_details ,则违反了相同规则。

我很想知道为什么会这样?

这是jsbin的链接:http://jsbin.com/asuzev/1/edit

最佳答案

下面的例子可以很容易地说明发生了什么:
通过原型(prototype)链访问personal_details

var person = { name :"dummy", personal_details: { age : 22, country : "USA" } }
var bob = Object.create(person)

bob.name = "bob"
bob.personal_details.age = 23
输出如下:
console.log( bob );
/// { name :"bob", personal_details: { age : 23, country : "USA" } }

console.log( person )
/// { name :"dummy", personal_details: { age : 23, country : "USA" } }
现在在人员对象上设置了23岁, because bob.personal_details是通过bob的原型(prototype)链直接引用 person.personal_details的对象。导航到对象结构后,就可以直接使用 person.personal_details对象。

用本地属性覆盖原型(prototype)属性
但是,如果用另一个对象覆盖bob的 personal_details属性,则该原型(prototype)链接将被更本地的属性覆盖。
bob.personal_details = { a: 123 }
现在的输出是:
console.log( bob );
/// { name :"bob", personal_details: { a : 123 } }

console.log( person )
/// { name :"dummy", personal_details: { age : 23, country : "USA" } }
因此,从现在开始,通过访问 bob.personal_details,您引用的是 { a: 123 }对象,而不是person的原始 { age : 23, country : "USA" }对象。所做的所有更改都将在该对象上发生,并且基本上与 bobperson对象无关。

原型(prototype)链
为了使事情变得有趣,完成以上所有操作后,您认为会发生什么:
delete bob.personal_details
您最终使原始原型(prototype)链接恢复为 person.personal_details(因为您已删除添加的本地属性),因此控制台日志将显示:
console.log( bob );
/// { name :"bob", personal_details: { age : 23, country : "USA" } }
基本上,JavaScript引擎将沿原型(prototype)链进行工作,直到找到每个原型(prototype)对象上要请求的属性或方法为止。项设置的距离越远,这意味着它将在以后向下覆盖其他项。
现在再问一个问题,如果再次触发以下命令会发生什么?
delete bob.personal_details
没有,不再分配给bob的实际属性称为 personal_detailsdelete将仅在当前对象上起作用,而不会遵循原型(prototype)链。

一种不同的看待方式
观察原型(prototype)链如何工作的另一种方法基本上是想象一堆对象。当JavaScript扫描特定的属性或方法时,它将通过以下结构向下读取:
bob :          {  }
person : { name: 'dummy', personal_details: { age: 22 } }
Object : { toString: function(){ return '[Object object]'; } }
因此,举例来说,我想访问 bob.toStringtoString是JavaScript基本对象 Object上存在的方法,该对象是几乎所有内容的基本原型(prototype)。当解释器获得对对象上特定方法或属性的读取请求时,它将遵循以下事件链:
  • bob是否具有称为toString的属性? 编号
  • bob.__proto__(即person)是否具有称为toString的属性? 编号
  • bob.__proto__.__proto__(即Object)是否具有称为toString的属性?
  • 返回对function(){ return '[Object object]'; }的引用

  • 一旦到达点4,解释器将返回对Object上 toString方法的引用。如果未在 Object上找到该属性,则很可能会触发未定义属性的错误(因为它是链中的最后一个)。
    现在,如果我们以前面的示例为例,这一次在 toString上定义 bob方法-因此:
    bob :          { toString: function(){ return '[Bob]'; } }
    person : { name: 'dummy', personal_details: { age: 22 } }
    Object : { toString: function(){ return '[Object object]'; } }
    如果我们尝试再次读取bob上的 toString方法,则这次得到:
  • bob是否具有称为toString的属性? 是。

  • 该过程在第一个障碍处停止,并从bob返回 toString方法。这意味着 bob.toString()将返回 [Bob]而不是 [Object object]
    正如Phant0m简洁指出的那样,对对象的写入请求将遵循不同的路径,并且永远不会沿原型(prototype)链向下移动。理解这一点是要弄清什么是读请求和什么是写请求之间的区别。
    bob.toString                   --- is a read request
    bob.toString = function(){} --- is a write request
    bob.personal_details --- is a read request
    bob.personal_details = {} --- is a write request
    bob.personal_details.age = 123 --- is a read request, then a write request.
    最后一项是引起困惑的一项。该过程将遵循以下路线:
  • bob是否具有称为personal_details的属性? 编号
  • person是否具有称为personal_details的属性? 是。
  • 返回对{ age: 22 }的引用,该引用存储在内存中的某个位置。

  • 现在开始新的过程,因为对象导航或分配的每个部分都是对属性或方法的新请求。因此,现在我们有了 personal_details对象,我们将其切换到写入请求,因为 = equals左侧的属性或变量始终是赋值。
  • 将值123写入对象age上的属性{ age: 22 }

  • 因此原始请求可以看作是这样的:
    (bob.personal_details)            --- read
    (personal_details.age = 123) --- write
    如果 bob拥有自己的 personal_details属性,则过程将相同,但是写入的目标对象将不同。

    最后...
    提出您的问题:

    Its difficult to digest that properties on prototype objects are treated as READ_ONLY, but if property is an object then one can get hold of it and can freely modify its properties !! Is my understanding right ?


    原型(prototype)属性看似只读,但仅当作为继承它们的对象的属性直接访问时才使用-因为这些属性实际上根本不在继承对象上存在。如果您向下浏览到原型(prototype)对象本身,则可以将其视为任何普通对象(具有读写功能),因为它就是所谓的普通对象。最初可能会造成混淆,但这是性质或原型(prototype)继承,而这完全取决于您如何访问要使用的属性。

    关于javascript - Javascript原型(prototype)继承和对象属性阴影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14379208/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com