Skip to content
Advertisement

Why can we define a setter with [[set]] if [[writable]] is false?

The ECMAScript language specification defines the [[writable]] attribute of Object.defineProperty() as following:

  • If false, attempts by ECMAScript code to change the property’s [[Value]] attribute using [[Set]] will not succeed.

However, this definition doesn’t make any sense. There it says that if [[writable]] is false, any attempts to use [[set]] will not work. So in other words: if [[writable]] is false then we can’t change it to an accessor property of a setter.

However, in the example below we have an object where we are able to define [[set]] despite [[writable]] being false:

var plainObj = new Object();

Object.defineProperty(plainObj, "v1", {
    configurable: true,
    writable: false, //<---- attribute [[writable]] is 'false'
    value: "handsome-and-SKINNY"
});

    //setting an [[set]] attribute:
    Object.defineProperty(plainObj, "v1", {
        set: function (input) {
            console.log("Setter's value: " + input);
        }
    });

    //passing argument to setter
    plainObj.v1 = "passed argument"; 

Console output:

Setter's value: passing argument

So as you can see, we have successfully defined an [[set]] attribute and passed in some arguments into it, despite the fact that it shoudn’t be happening because [[writable]] was set to false. Any explenations are appreciated.

Advertisement

Answer

If false, attempts by ECMAScript code to change the property’s [[Value]] attribute using [[Set]] will not succeed.

However, this definition doesn’t make any sense. There it says that if [[writable]] is false, any attempts to use [[set]] will not work.

You misunderstood the specification.

When the property is a data property, it is defined by the [[Value]] and [[Writable]] attributes, [[Get]] and [[Set]] are not present. When the property is an accessor property, it is defined by the [[Get]] and [[Set]] attributes, [[Value]] and [[Writable]] are not present.

The phrase “change the property’s [[Value]] attribute using [[Set]] will not succeed.” does not refer to the [[Set]] attribute of a data property descriptor record, it refers to the [[Set]]() internal object method which will not succeed.

Your example code did change the data property into an accessor property, thereby also removing the [[Writable]] attribute. It now can be written to as long as there is a setter.

Advertisement