Skip to content

The subtle difference between property assignment and definition #20

Description

@Ayms

This is not exactly a regret but "how it works" or "why it is like this", trying to explain here the subtle difference between property assignment (=) and property definition (defineProperty), I hope this is not confusing (comments, corrections are welcome), apparently we need to get used to it :

var HTMLElement=function() {};

HTMLElement.prototype={
    get innerHTML() {return this.html_},
    set innerHTML(val) {this.html_=val},
    a: 'a'
};

var DIV=new HTMLElement();

DIV.innerHTML='c';
// Assignment operator "=", called as '[[Put]' below.

// If the property (own or inherited) does exist, is not an accessor and is 
// allowed to be modified, this creates a new own property 'innerHTML' 
// (if the property is inherited) or modifies the existing one.

// If the property does not exist, this creates a new own property 'innerHTML'.

// If the property is an accessor, this does trigger the accessor 
// (our case here).

console.log(DIV.innerHTML); //c
// OK, normal

Object.defineProperty(DIV,'innerHTML',{value:'b',writable : true,enumerable : true,configurable : true});
// Called as '[[DefineOwnProperty]]' below.

// This does define or modify a new 'innerHTML' own property that will 
// be returned prior to the inherited one (if it exists, our case here).

console.log(DIV.innerHTML); //b
// OK, so what ?
// Now consider for example http://wiki.ecmascript.org/doku.php?id=strawman:object_extension_literals
// To make it short the proposal is about extending an object literal :
// DIV.{width:'100px',height:'100px'}
// Surprisingly, the proposal does allow to do :
// DIV.{width='100px',height='100px'}
// the difference is that ':' stands for [[DefineOwnProperty]]
// and '=' for [[Put]]
// OK, surprising, but so what ? (again)
// Now consider that while coding, you might do :
// DIV.{innerHTML:'my html'}
// This will not have the effect you could expect, but just create a new 
// 'innerHTML' own property, therefore your div will not contain 'my html'
// Instead, you should have written :
// DIV.{innerHTML='my html'}

delete DIV.innerHTML;
// Delete the own property

console.log(DIV.innerHTML); // c
// Returns the inherited one

//Other example
console.log(DIV.a); //a
// Inherited property

DIV.a='b';

console.log(DIV.a); //b
// New own property

Object.defineProperty(DIV,'a',{value:'c',writable : true,enumerable : true,configurable : true});
// Modify the own property

console.log(DIV.a); //c

delete DIV.a;
// Delete the own property

console.log(DIV.a); //a
// Returns the inherited property

Maybe this sentence from Brendan Eich can summarize what is happening : "There really is a difference between assigning and defining in JS. Assigning runs setters, even inherited ones. Defining overrides or shadows."

Other examples can be found here : http://wiki.ecmascript.org/doku.php?id=strawman:define_properties_operator

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions