This is the 30th day of my participation in the August Wen Challenge.More challenges in August

Property Settings and masking

In JavaScript, setting a property for an object is not just about adding a new property or changing an existing property value. Let’s take a look at this process:

    myObject.foo = "bar";
Copy the code

If myObject contains a common data access attribute named foo, this assignment statement will only modify the existing attribute value.

If Foo does not exist directly in myObject, the [prototype] chain is iterated, similar to the [Get] operation. If foo is not found on the entire prototype chain, it is added directly to myObject.

Masking occurs if Foo appears both in myObject and at the top of the Prototype chain of myObject. The foo property contained in myObject will mask all foo properties at the top of the prototype chain, because MyObject. foo always selects the foo property at the bottom of the prototype chain.

But shielding is not as easy as it seems. Here are three cases where Foo exists not directly in myObject but at the top of the prototype chain:

  1. If there is a common data access property named foo at the top of the [prototype] chain and that property is not marked as writable:ture, a new property named foo is added directly to myObject, which is a masked property.
  2. If foo exists at the top of the [prototype] chain, but the property is marked as read-only (writable:false), there is no way to modify an existing property or create a masked property on myObject. If run in strict mode, the code throws an error. Otherwise, it will be ignored and no masking will occur.
  3. If foo exists at the top of the [prototype] chain and it has a setter, that setter must be called. Foo will not be added to (or shielded from) myObject, nor will the setter foo be redefined.

Read-only properties prevent [Prototype] from implicitly creating (masking) properties of the same name below the chain. This is done primarily to simulate inheritance of class attributes. We can think of foo at the top of the prototype chain as a property in the parent class, which is inherited (copied) by myObject, so that foo in myObject is also read-only and therefore cannot be created. But let’s be clear, no such inheritance replication actually occurs. It is confusing that myObject cannot contain foo because there is a read-only foo among other objects. To make things even more confusing, this restriction only applies to = assignments and using Object.defineProperty() is not affected.

Some cases also implicitly create masking:

     var anotherObj={
        a : 2
    };
    // Create an object associated with anotherObj
    var myObj = Object.create(anotherObj);
    console.log(anotherObj.a);       / / 2
    console.log(myObj.a);            / / 2
    anotherObj.hasOwnProperty("a")   //true
    myObj.hasOwnProperty("a")        //false
    myObj.a++;                       // implicit masking!
    console.log(anotherObj.a);       / / 2
    console.log(myObj.a);            / / 3
    myObj.hasOwnProperty("a")        //true
Copy the code

Although myobj.a ++ looks like it should find and add the anotherobj.a property, the ++ operation is equivalent to myobj.a = myobj.a + 1. So the ++ operation first looks for attribute A through [prototype] and gets the current attribute value 2 from anotherObject.a, then increses that value by 1, and assigns 3 to the new masked attribute A in myObject with [Put].