Javascript 文字实例创建行为各不相同

Javascript 文字实例创建行为各不相同,javascript,object,object-literal,Javascript,Object,Object Literal,我有一个object literal,里面有另一个literal。 父实例可以很好地设置值,但不能设置内部值。 我对这种行为感到困惑。 为什么对象文字的行为不同 这是你的电话号码 这不是一个重复的问题 我知道其他选择 我知道内部文字将覆盖我看到了很多例子 我不知道为什么父对象不重复相同的行为 为什么在我的示例中car.tires值正确显示而不是被覆盖 编辑:在末尾添加了一些内容并进行了更正 我觉得我们需要在这里写下答案。如果这是不礼貌的(如果这是错误的答案),我道歉。请让我知道 原型继承在ja

我有一个object literal,里面有另一个literal。 父实例可以很好地设置值,但不能设置内部值。 我对这种行为感到困惑。
为什么对象文字的行为不同

这是你的电话号码

这不是一个重复的问题

  • 我知道其他选择
  • 我知道内部文字将覆盖我看到了很多例子
  • 我不知道为什么父对象不重复相同的行为

    为什么在我的示例中car.tires值正确显示而不是被覆盖


  • 编辑:在末尾添加了一些内容并进行了更正

    我觉得我们需要在这里写下答案。如果这是不礼貌的(如果这是错误的答案),我道歉。请让我知道

    原型继承在javascript中的工作方式:
    当您读取对象的属性时,让我们假设
    汽车
    对象的
    轮胎
    属性,首先它检查
    汽车
    本身是否具有该属性。这意味着,是否有一个
    轮胎
    属性直接连接到
    汽车
    对象?或者换句话说,
    Car
    是这样的:

    {
        tires: 0,
        ...
    }
    
    {
        tires: 6,
        __proto__: //reference to vehicle
    }
    
    答案是否定的。您可能会认为
    Object.create()
    可以做到这一点,类似于您在构造函数中所做的,即

    function Vehice(t) {
        this.tires = t;
        ...
    };
    var Car = new Vehicle(4);
    
    Object.create()
    所做的一切就是将您传递的对象放入它返回给您的对象的
    prototype

    因此,在
    Object.create()之后,您的对象如下所示

    {
        __proto__: //reference to vehicle
    }
    
    因此,当它没有找到直接连接到对象的
    轮胎
    时,它会查看原型,在本例中是对您先前创建的
    车辆
    对象的引用。原型(
    车辆
    不具有
    轮胎
    属性,因此它返回该值

    校正

    那么当你说Car.tires=6时会发生什么呢?当您将值写入对象属性时,情况会有所不同。Javascript只查看对象本身是否有要写入的属性。如果对象本身没有该属性,它首先检查原型链以确保该属性不是继承的只读属性。如果不是,它将在对象本身上创建该属性(只要将该属性写入对象是合法的)。现在你有了这样的东西:

    {
        tires: 0,
        ...
    }
    
    {
        tires: 6,
        __proto__: //reference to vehicle
    }
    
    结束修正

    现在,当您读取
    Car
    对象上的
    tires
    属性时,它首先会看到
    Car
    对象本身上的
    tires
    属性并返回该值,而无需查看原型

    这就是为什么您可以在一辆车上设置
    轮胎
    属性,而不影响其他车辆的值

    现在查看
    seats.total
    属性。当您从
    seats
    属性中读取时,一切都与以前一样工作。
    Car
    对象本身没有
    seats
    属性,因此它看起来像原型,而原型确实拥有它。然后它检查
    seats
    引用的对象,看看它是否有一个直接附加到它的
    total
    属性,它有,所以它只返回该值

    现在,当您想写入
    total
    属性时,情况又不同了。声明如下:
    Car.seats.total=4
    。这里发生的情况是,您正在对
    seats
    属性所引用的对象设置
    total
    属性

    Javascript首先必须找到
    seats
    引用的对象。它通过检查它是否是
    Car
    对象本身的属性来实现这一点。它不是,因此它检查原型,在原型中找到
    seats
    属性。现在它可以像我们前面看到的那样将
    total
    属性写入
    seats
    对象,但是请注意,这发生在原型的
    seats
    属性上,它是对
    车辆
    对象的引用,该对象以前定义并由
    自行车
    共享

    换句话说,javascript没有看到您正在写入
    Car
    对象的属性,因此它不会在
    Car
    对象上创建
    seats
    属性并为其分配一个新对象,然后在该对象上创建
    total
    属性并为其分配
    4

    现在,当您尝试读取
    bike
    seats
    属性时,javascript首先查看
    bike
    是否有一个
    seats
    属性直接连接到它。它没有,所以它看起来像是
    bike
    的原型,它确实拥有它并返回修改后的
    vehicle.seats
    对象

    我希望这能澄清正在发生的事情并回答你的问题。如果有任何部分不清楚,请告诉我,如果我完全错了,我希望有人会纠正我

    附录:我认为来自传统OO语言的
    轮胎
    的工作方式是您所期望的:您继承初始值,但如果您更改它,您不会期望它在
    车辆
    的每一个其他实例中都会更改

    javascript这样做非常节省空间。仅通过最初使原型具有该属性,如果您有一千个对象继承自
    车辆
    ,并且其中只有两个对象设置了
    轮胎
    属性,那么您只使用了三个
    数字
    的空间,而不是一千个

    至于它如何处理
    座位
    ,我想他们可能设计了一种语言来检测您是否在继承的
    对象
    座位
    )上设置属性,然后将整个对象复制到
    var car2 = Object.create(vehicle);
    car2.seats = { count: vehicle.seats.total }; //create a new object like the one attached to vehicle