Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can ES6 Symbol properties be made enumerable by Object.defineProperty?

Tags:

In ES6 properties can be defined as symbol properties:

var symbol = Symbol();
var object = {};
object[symbol] = 'value';

MDN defines enumerable properties as 'those which can be iterated by a for..in loop' (1). Symbol properties are never iterated by a for...in loop, therefore they can be considered non-enumerable (2).

Does it make any sense, then, that you can do this:

Object.defineProperty(object, symbol, {
    value: 'value',
    enumerable: true
});

and that querying object for it's descriptor does indeed confirm that this property is enumerable:

Object.getOwnPropertyDescriptor(object, symbol)
// -> { enumerable: true }

Why? What use is this?

(1) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties

(2) for...in uses [[Enumerate]], which only includes string keys. Probably the definition on MDN should be changed now that we have symbol properties.

like image 275
stephband Avatar asked Jun 24 '15 14:06

stephband


People also ask

Are symbol properties enumerable?

MDN defines enumerable properties as 'those which can be iterated by a for..in loop' (1). Symbol properties are never iterated by a for...in loop, therefore they can be considered non-enumerable (2).

What does it mean for an object property to be enumerable?

Enumerable properties are those properties whose internal enumerable flag is set to true, which is the default for properties created via simple assignment or via a property initializer. Properties defined via Object.

What is the syntax of object defineProperty () method in JavaScript?

Syntax: Object. defineProperty(obj, prop, descriptor)

What are symbols in ES6 And why would you use them?

Symbols are new primitive type introduced in ES6. Symbols are completely unique identifiers. Just like their primitive counterparts (Number, String, Boolean), they can be created using the factory function Symbol() which returns a Symbol. Every time you call the factory function, a new and unique symbol is created.


1 Answers

Yes, there's a reason for allowing Symbol properties to be enumerable: Object.assign:

let s1 = Symbol();
let s2 = Symbol();
let s3 = Symbol();
let original = {};
original[s1] = "value1";                // Enumerable
Object.defineProperty(original, s2, {   // Enumerable
  enumerable: true,
  value: "value2"
});
Object.defineProperty(original, s3, {   // Non-enumerable
  value: "value3"
});
let copy = {};
Object.assign(copy, original);
console.log("copy[s1] is " + copy[s1]); // value1, because it was enumerable
console.log("copy[s2] is " + copy[s2]); // value2, because it was enumerable
console.log("copy[s3] is " + copy[s3]); // undefined, because it wasn't enumerable

Live Copy on Babel's REPL.

Just for clarity:

MDN defines enumerable properties as 'those which can be iterated by a for..in loop' (1).

That's simply wrong for ES6 (ES2015). It was a reasonable, if simplistic, definition in ES5 and earlier, no it's no longer even simplistically correct because of Symbols. I've fixed the article.


This is a CW because it was the outgrowth of the comments on the question.

like image 71
4 revs Avatar answered Sep 28 '22 03:09

4 revs