[[classes-symbols-objects-and-decorators]]
== Classes, Symbols, Objects, pass:[<span class="keep-together">and Decorators</span>]

Now that we've covered the basic improvements to the syntax, we're in good shape to take aim at a few other additions to the language: classes and symbols. Classes provide syntax to represent prototypal inheritance under the traditional class-based programming paradigm. Symbols are a new primitive value type in JavaScript, like strings, Booleans, and numbers. They can be used for defining protocols, and in this chapter we'll investigate what that means. When we're done with classes and symbols, we'll discuss a few new static methods added to the `Object` built-in in ES6.

=== Classes

JavaScript ((("classes", id="class3")))is a prototype-based language, and classes are mostly syntactic sugar on top of prototypal inheritance. The fundamental difference between ((("prototypal inheritance")))((("classes", "versus prototypal inheritance", secondary-sortas="prototypal")))prototypal inheritance and classes is that classes can `extend` other classes, making it possible for us to extend the `Array` built-in--something that was very convoluted before ES6.

The `class` keyword acts, then, as a device that makes JavaScript more inviting to programmers coming from other paradigms, who might not be all that familiar with prototype chains.

==== Class Fundamentals

When ((("classes", "fundamentals", id="class3f")))learning about new language features, it's always a good idea to look at existing constructs first, and then see how the new feature improves those use cases. We'll start by looking at a simple prototype-based JavaScript constructor and then compare that with the newer classes syntax in ES6.

The following code snippet ((("classes", "class declaration syntax", id="class3cds")))represents a fruit using a ((("constructor()", id="cf3")))constructor function and adding a couple of methods to the prototype. The constructor function takes a `name` and the amount of `calories` for a fruit, and defaults to the fruit being in a single piece. There's a `.chop` method that will slice another piece of fruit, and then there's a `.bite` method. The `person` passed into `.bite` will eat a piece of fruit, getting satiety equal to the remaining calories divided by the amount of fruit pieces left.

[source,javascript]
----
function Fruit(name, calories) {
  this.name = name
  this.calories = calories
  this.pieces = 1
}
Fruit.prototype.chop = function () {
  this.pieces++
}
Fruit.prototype.bite = function (person) {
  if (this.pieces < 1) {
    return
  }
  const calories = this.calories / this.pieces
  person.satiety += calories
  this.calories -= calories
  this.pieces--
}
----

While fairly simple, the piece of code we just put together should be enough to note a few things. We have a constructor function that takes a couple of parameters, a pair of methods, and a number of properties. The next snippet codifies how one should create a `Fruit` and a `person` that chops the fruit into four slices and then takes three bites.

[source,javascript]
----
const person = { satiety: 0 }
const apple = new Fruit('apple', 140)
apple.chop()
apple.chop()
apple.chop()
apple.bite(person)
apple.bite(person)
apple.bite(person)
console.log(person.satiety)
// <- 105
console.log(apple.pieces)
// <- 1
console.log(apple.calories)
// <- 35
----

When using `class` syntax, as shown in the following code listing, the `constructor` function is declared as an explicit member of the `Fruit` class, and methods follow the object literal method definition syntax. When we compare the `class` syntax with the prototype-based syntax, you'll notice we're reducing the amount of boilerplate code quite a bit by avoiding explicit references to `Fruit.prototype` while declaring methods. The fact that the entire declaration is kept inside the `class` block also helps the reader understand the scope of this piece of code, making our classes' intent clearer. Lastly, having the constructor explicitly as a method member of `Fruit` makes the `class` syntax easier to understand when compared with the prototype-based ((("constructor()", startref="cf3")))flavor of class syntax.

[source,javascript]
----
class Fruit {
  constructor(name, calories) {
    this.name = name
    this.calories = calories
    this.pieces = 1
  }
  chop() {
    this.pieces++
  }
  bite(person) {
    if (this.pieces < 1) {
      return
    }
    const calories = this.calories / this.pieces
    person.satiety += calories
    this.calories -= calories
    this.pieces--
  }
}
----

A not-so-minor detail you might have missed is that there aren't any commas in ((("classes", "commas in class syntax")))between method declarations of the `Fruit` class. That's not a mistake our copious copyeditors missed, but rather part of the `class` syntax. The distinction can help avoid mistakes where we treat plain objects and classes as interchangeable even though they're not, and at the same time it makes classes better suited for future improvements to the syntax such as public and private class fields.

The class-based solution is equivalent to the prototype-based piece of code we wrote earlier. Consuming a fruit wouldn't change in the slightest; the API for `Fruit` remains unchanged. The previous piece of code where we instantiated an apple, chopped it into smaller pieces, and ate most of it would work well with our `class`-flavored `Fruit` as well.

It's worth noting that class declarations aren't hoisted to the top of their scope, unlike function declarations. That means you won't be able to instantiate, or otherwise access, a class before its declaration is reached and executed.

[source,javascript]
----
new Person() // <- ReferenceError: Person is not defined
class Person {
}
----

Besides ((("classes", "class declaration syntax", startref="class3cds")))the class declaration syntax presented earlier, classes can also be declared as ((("classes", "expression syntax", id="class3es")))expressions, just like with function declarations and function expressions. You may omit the name for a `class` expression, as shown in the following bit of code.

[source,javascript]
----
const Person = class {
  constructor(name) {
    this.name = name
  }
}
----

Class expressions could be easily returned from a function, making it possible to create a factory of classes with minimal effort. In the following example we create a `JakePerson` class dynamically in an arrow function that takes a `name` parameter and then feeds that to the parent `Person` constructor via `super()`.

[source,javascript]
----
const createPersonClass = name => class extends Person {
  constructor() {
    super(name)
  }
}
const JakePerson = createPersonClass('Jake')
const jake = new JakePerson()
----

We'll dig deeper into class inheritance later. Let's take a more nuanced look at properties and methods ((("classes", "fundamentals", startref="class3f")))first.

==== Properties and Methods in Classes

It ((("classes", "properties and methods in", id="class3pami")))((("properties", id="p3ic")))((("methods", id="m3ic")))should be noted that the `constructor` ((("constructor()")))method declaration is an optional member of a `class` declaration. The following bit of code shows an entirely valid `class` declaration that's comparable to an empty constructor function by the same name.

[source,javascript]
----
class Fruit {
}
function Fruit() {
}
----

Any arguments passed to `new Log()` will be received as parameters to the `constructor` method for `Log`, as depicted next. You can use those parameters to initialize instances of the class.

[source,javascript]
----
class Log {
  constructor(...args) {
    console.log(args)
  }
}
new Log('a', 'b', 'c')
// <- ['a' 'b' 'c']
----

The following example shows a class where we create and initialize an instance property named `count` upon construction of each instance. The `get next` method declaration indicates instances of our `Counter` class will have a `next` property that will return the results of calling its method, whenever that property is accessed.

[source,javascript]
----
class Counter {
  constructor(start) {
    this.count = start
  }
  get next() {
    return this.count++
  }
}
----

In this case, you could consume the `Counter` class as shown in the next snippet. Each time the `.next` property is accessed, the count raises by one. While mildly useful, this sort of use case is usually better suited by methods than by ((("getters")))magical `get` ((("accessors", id="acc3")))property accessors, and we need to be careful not to abuse property accessors, as consuming an object that abuses of accessors may become very confusing.

[source,javascript]
----
const counter = new Counter(2)
console.log(counter.next)
// <- 2
console.log(counter.next)
// <- 3
console.log(counter.next)
// <- 4
----

When paired with ((("setters")))setters, though, accessors may provide an interesting bridge between an object and its underlying data store. Consider the following example where we define a class that can be used to store and retrieve JSON data from `localStorage` using the provided storage `key`.

[source,javascript]
----
class LocalStorage {
  constructor(key) {
    this.key = key
  }
  get data() {
    return JSON.parse(localStorage.getItem(this.key))
  }
  set data(data) {
    localStorage.setItem(this.key, JSON.stringify(data))
  }
}
----

Then you could use the `LocalStorage` class as shown in the next example. Any value that's assigned to `ls.data` will be converted to its JSON object string representation and stored in `localStorage`. Then, when the property is read from, the same `key` will be used to retrieve the previously stored contents, parse them as JSON into an object, and returned.

[source,javascript]
----
const ls = new LocalStorage('groceries')
ls.data = ['apples', 'bananas', 'grapes']
console.log(ls.data)
// <- ['apples', 'bananas', 'grapes']
----

Besides getters and setters, you can also define regular instance methods, as we've explored earlier when creating the `Fruit` class. The following code example creates a `Person` class that's able to eat `Fruit` instances as we had declared them earlier. We then instantiate a fruit and a person, and have the person eat the fruit. The person ends up with a satiety level equal to `40`, because he ate the whole fruit.

[source,javascript]
----
class Person {
  constructor() {
    this.satiety = 0
  }
  eat(fruit) {
    while (fruit.pieces > 0) {
      fruit.bite(this)
    }
  }
}
const plum = new Fruit('plum', 40)
const person = new Person()
person.eat(plum)
console.log(person.satiety)
// <- 40
----

Sometimes it's necessary to add static methods at the class level, rather than members at the instance level. Using syntax available before ES6, instance members have to be explicitly added to the prototype chain. Meanwhile, static methods should be added to the constructor directly.

[source,javascript]
----
function Person() {
  this.hunger = 100
}
Person.prototype.eat = function () {
  this.hunger--
}
Person.isPerson = function (person) {
  return person instanceof Person
}
----

JavaScript classes allow you to define ((("static methods")))static methods like `Person.isPerson` using the `static` keyword, much like you would use `get` or `set` as a prefix to a method definition that's a getter or a setter.

The following example defines a `MathHelper` class with a static `sum` method that's able to calculate the sum of all numbers passed to it in a function call, by taking advantage of the `Array#reduce` method.

[source,javascript]
----
class MathHelper {
  static sum(...numbers) {
    return numbers.reduce((a, b) => a + b)
  }
}
console.log(MathHelper.sum(1, 2, 3, 4, 5))
// <- 15
----

Finally, it's worth mentioning that you could also declare static property ((("accessors", startref="acc3")))accessors, such as ((("getters")))((("setters")))getters or setters (`static get`, `static set`). These might come in handy when maintaining global configuration state for a class, or when a class is used under a singleton pattern. Of course, you're probably better off using plain old JavaScript objects at that point, rather than creating a class you never intend to instantiate or only intend to instantiate once. This is JavaScript, a highly dynamic language, ((("classes", "properties and methods in", startref="class3pami")))((("properties", "in classes", startref="p3ic")))((("methods", "in classes", startref="m3ic")))after all.

==== Extending JavaScript Classes

You ((("classes", "extending", id="class3ext")))could use plain JavaScript to extend the `Fruit` class, but as you will notice by reading the next code snippet, declaring a subclass involves esoteric knowledge such as `Parent.call(this)` in order to pass in parameters to the parent class so that we can properly initialize the subclass, and setting the prototype of the subclass to an instance of the parent class's prototype. As you can readily find heaps of information about ((("prototypal inheritance", id="pi3)))prototypal inheritance around the web, we won't be delving into detailed minutia about prototypal inheritance.

[source,javascript]
----
function Banana() {
  Fruit.call(this, 'banana', 105)
}
Banana.prototype = Object.create(Fruit.prototype)
Banana.prototype.slice = function () {
  this.pieces = 12
}
----

Given the ephemeral knowledge one has to remember, and the fact that `Object.create` ((("Object.create")))was only made available in ES5, JavaScript developers have historically turned to libraries to resolve their prototype inheritance issues. One such example is `util.inherits` in Node.js, which ((("util.inherits")))is usually favored over `Object.create` for legacy support reasons.

[source,javascript]
----
const util = require('util')
function Banana() {
  Fruit.call(this, 'banana', 105)
}
util.inherits(Banana, Fruit)
Banana.prototype.slice = function () {
  this.pieces = 12
}
----

Consuming the `Banana` constructor is no different than how we used `Fruit`, except that the banana has a `name` and calories already assigned to it, and they come with an extra `slice` method we can use to promptly chop the banana instance into 12 pieces. The following piece of code shows the `Banana` in action as we take a bite.

[source,javascript]
----
const person = { satiety: 0 }
const banana = new Banana()
banana.slice()
banana.bite(person)
console.log(person.satiety)
// <- 8.75
console.log(banana.pieces)
// <- 11
console.log(banana.calories)
// <- 96.25
----

Classes consolidate prototypal inheritance, which up until recently had been highly contested in user-space by several libraries trying to make it easier to deal with prototypal inheritance in JavaScript.

The `Fruit` class is ripe for inheritance. In the following code snippet we create the `Banana` class as an extension of the `Fruit` class. Here, the syntax clearly signals our intent and we don't have to worry about thoroughly understanding prototypal inheritance in order to get to the results that we want. When we want to forward parameters to the underlying `Fruit` constructor, we can use `super`. The `super` keyword can also be used to call functions in the parent class, such as `super.chop`, and it's not just limited to the constructor for the parent class.

[source,javascript]
----
class Banana extends Fruit {
  constructor() {
    super('banana', 105)
  }
  slice() {
    this.pieces = 12
  }
}
----

Even though the `class` keyword is static we can still leverage JavaScript's flexible and functional properties when declaring classes. Any expression that returns a constructor function can be fed to `extends`. For example, we could have a constructor function factory and use that as the base class.

The following piece of code has a `createJuicyFruit` function where we forward the name and calories for a fruit to the `Fruit` class using a `super` call, and then all we have to do to create a `Plum` is extend the intermediary `JuicyFruit` class.

[source,javascript]
----
const createJuicyFruit = (...params) =>
  class JuicyFruit extends Fruit {
    constructor() {
      this.juice = 0
      super(...params)
    }
    squeeze() {
      if (this.calories <= 0) {
        return
      }
      this.calories -= 10
      this.juice += 3
    }
  }
class Plum extends createJuicyFruit('plum', 30) {
}
----

Let's move ((("prototypal inheritance", startref="pi3)))onto `Symbol`. While not an iteration or flow control mechanism, learning about `Symbol` is crucial to shaping an understanding of iteration protocols, which are discussed at length in ((("classes", startref="class3")))((("classes", "extending", startref="class3ext")))the next chapter.

=== Symbols

Symbols ((("symbols", id="sym3")))are a new primitive type in ES6, and the seventh type in JavaScript. It is a unique value type, like strings and numbers. Unlike strings and numbers, symbols don't have a literal representation such as `'text'` for strings, or `1` for numbers. The purpose of symbols is primarily to ((("symbols", "defining protocols through")))implement protocols. For example, the iterable protocol ((("iterable protocol")))uses a symbol to define how objects are iterated, as we'll learn in <<iterator_protocol_and_iterable_protocol>>.

There are three flavors of symbols, and each flavor is accessed in a different way. These are: local symbols, created with the `Symbol` built-in wrapper object and accessed by storing a reference or via reflection; global symbols, created using another API and shared across code realms; and "well-known" symbols, built into JavaScript and used to define internal language behavior.

We'll explore each of these, looking into possible use cases along the way. Let's begin with local symbols.

==== Local Symbols

Symbols ((("symbols", "local", id="sym3l")))((("local symbols", id="ls3")))can be created using the `Symbol` wrapper object. In the following piece of code, we create our `first` symbol.

[source,javascript]
----
const first = Symbol()
----

While you can use the `new` keyword with `Number` and `String`, the `new` operator throws a `TypeError` when we try it on `Symbol`. This avoids mistakes and confusing behavior like `new Number(3) !== Number(3)`. The following snippet shows the error being thrown.

[source,javascript]
----
const oops = new Symbol()
// <- TypeError, Symbol is not a constructor
----

For ((("symbols", "for debugging")))debugging purposes, you can create symbols using a description.

[source,javascript]
----
const mystery = Symbol('my symbol')
----

Like numbers or strings, symbols are immutable. Unlike other value types, however, symbols are unique. As shown in the next piece of code, descriptions don't affect that uniqueness. Symbols created using the same description are also unique and thus different from each other.

[source,javascript]
----
console.log(Number(3) === Number(3))
// <- true
console.log(Symbol() === Symbol())
// <- false
console.log(Symbol('my symbol') === Symbol('my symbol'))
// <- false
----

Symbols are of type `symbol`, new in ES6. The following snippet shows how `typeof` returns the new type string for symbols.

[source,javascript]
----
console.log(typeof Symbol())
// <- 'symbol'
console.log(typeof Symbol('my symbol'))
// <- 'symbol'
----

Symbols can be used as ((("symbols", "as property keys")))property keys on objects. Note how you can use a computed property name to avoid an extra statement just to add a `weapon` symbol key to the `character` object, as shown in the following example. Note also that, in order to access a symbol property, you'll need a reference to the symbol that was used to create said property.

[source,javascript]
----
const weapon = Symbol('weapon')
const character = {
  name: 'Penguin',
  [weapon]: 'umbrella'
}
console.log(character[weapon])
// <- 'umbrella'
----

Keep in mind that ((("symbols", "hidden properties of")))symbol keys are hidden from many of the traditional ways of pulling keys from an object. The next bit of code shows how `for..in`, `Object.keys`, and `Object.getOwnPropertyNames` fail to report on symbol properties.

[source,javascript]
----
for (let key in character) {
  console.log(key)
  // <- 'name'
}
console.log(Object.keys(character))
// <- ['name']
console.log(Object.getOwnPropertyNames(character))
// <- ['name']
----

This aspect of symbols means that code that was written before ES6 and without symbols in mind won't unexpectedly start stumbling upon symbols. In a similar fashion, as shown next, symbol properties are discarded when representing an object as JSON.

[source,javascript]
----
console.log(JSON.stringify(character))
// <- '{"name":"Penguin"}'
----

That being said, symbols are by no means a safe mechanism to conceal properties. Even though you won't stumble upon symbol properties when using pre-ES6 reflection, iteration or serialization methods, symbols are revealed by a dedicated method as shown in the next snippet of code. In other words, symbols are not nonenumerable, but hidden in plain sight. Using `Object.getOwnPropertySymbols` we can retrieve all symbols used as property keys on any given object.

[source,javascript]
----
console.log(Object.getOwnPropertySymbols(character))
// <- [Symbol(weapon)]
----

Now that we've established how symbols work, what can we use ((("symbols", "local", startref="sym3l")))((("local symbols", startref="ls3")))them for?

==== Practical Use Cases for Symbols

Symbols ((("symbols", "use cases for", id="sym3ucf")))((("symbols", "for DOM element mapping", id="sym3fdomem")))could be used by a library to map objects to DOM elements. For example, a library that needs to associate the API object for a calendar to the provided DOM element. Before ES6, there wasn't a clear way of mapping DOM elements to objects. You could add a property to a DOM element pointing to the API, but polluting DOM elements with custom properties is a bad practice. You have to be careful to use property keys that won't be used by other libraries, or worse, by the language itself in the future. That leaves you with using an array lookup table containing an entry for each DOM/API pair. That, however, might be slow in long-running applications where the array lookup table might grow in size, slowing down the lookup operation over time.

Symbols, on the other hand, don't have this problem. They can be used as properties that don't have a risk of clashing with future language features, as they're unique. The following code snippet shows how a symbol could be used to map DOM elements into calendar API objects.

[source,javascript]
----
const cache = Symbol('calendar')
function createCalendar(el) {
  if (cache in el) { // does the symbol exist in the element?
    return el[cache] // use the cache to avoid re-instantiation
  }
  const api = el[cache] = {
    // the calendar API goes here
  }
  return api
}
----

There is an ((("symbols", "for DOM element mapping", startref="sym3fdomem")))ES6 built-in--the ++WeakMap++—that ((("WeakMap")))can be used to uniquely map objects to other objects without using arrays or placing foreign properties on the objects we want to be able to look up. In contrast with array lookup tables, `WeakMap` lookups are constant in time or O(1). We'll explore `WeakMap` in <<leveraging-ecmascript-collections>>, alongside other ES6 collection built-ins.

===== Defining protocols through symbols

Earlier, ((("symbols", "defining protocols through", id="sym3dpt")))((("protocols", id="p3dts")))we posited that a use case for symbols is to define protocols. A protocol is a communication contract or convention that defines behavior. In less abstract terms, a library could use a symbol that could then be used by objects that adhere to a convention from the library.

Consider the following bit of code, where we use the special `toJSON` method to determine the object serialized by `JSON.stringify`. As you can see, stringifying the `character` object produces a serialized version of the object returned by `toJSON`.

[source,javascript]
----
const character = {
  name: 'Thor',
  toJSON: () => ({
    key: 'value'
  })
}
console.log(JSON.stringify(character))
// <- '"{"key":"value"}"'
----

In contrast, if `toJSON` was anything other than a function, the original `character` object would be serialized, including the `toJSON` property, as shown next. This sort of inconsistency ensues from relying on regular properties to define behavior.

[source,javascript]
----
const character = {
  name: 'Thor',
  toJSON: true
}
console.log(JSON.stringify(character))
// <- '"{"name":"Thor","toJSON":true}"'
----

The reason why it would be better to implement the `toJSON` modifier as a symbol is that that way it wouldn't interfere with other object keys. Given that symbols are unique, never serialized, and never exposed unless explicitly requested through `Object.getOwnPropertySymbols`, ((("Object.getOwnPropertySymbol")))they would represent a better choice when defining a contract between `JSON.stringify` and how objects want to be serialized. Consider the following piece of code with an alternative implementation of `toJSON` using a symbol to define serialization behavior for a `stringify` function.

[source,javascript]
----
const json = Symbol('alternative to toJSON')
const character = {
  name: 'Thor',
  [json]: () => ({
    key: 'value'
  })
}
stringify(character)
function stringify(target) {
  if (json in target) {
    return JSON.stringify(target[json]())
  }
  return JSON.stringify(target)
}
----

Using a symbol means we need to use a computed property name to define the `json` behavior directly on an object literal. It also means that the behavior won't clash with other user-defined properties or upcoming language features we couldn't foresee. Another difference is that the `json` symbol should be available to consumers of the `stringify` function, so that they can define their own behavior. We could easily add the following line of code to expose the `json` symbol directly through `stringify`, as shown next. That'd also tie the `stringify` function with the symbol that modifies its behavior.

[source,javascript]
----
stringify.as = json
----

By exposing the `stringify` function we'd be exposing the `stringify.as` symbol as well, allowing consumers to tweak behavior by minimally modifying objects, using the custom symbol.

When it comes to the merits of using a symbol to describe behavior, as opposed to an option passed to the `stringify` function, there are a few considerations to keep in mind. First, adding option parameters to a function changes its public API, whereas changing the internal implementation of the function to support another symbol wouldn't affect the public API. Using an `options` object with different properties for each option mitigates this effect, but it's not always convenient to require an `options` object in every function call.

A benefit of defining behavior via symbols is that you could augment and customize the behavior of objects without changing anything other than the value assigned to a symbol property and perhaps the internal implementation of the piece of code that leverages that behavior. The benefit of using symbols over properties is that you're not subject to name clashes when new language features are introduced.

Besides local symbols, there's also a global symbol registry, accessible from across code realms. Let's look into what ((("symbols", "use cases for", startref="sym3ucf")))((("symbols", "defining protocols through", startref="sym3dpt")))((("protocols", startref="p3dts")))that means.

==== Global Symbol Registry

A code ((("symbols", "global symbol registry", id="sym3gsr")))((("global symbol registry", id="gsr3")))realm is any JavaScript execution context, such as the page your application is running in, an `<iframe>` within that page, a script running through `eval`, or a worker of any kind--such as web workers, service workers, or shared workers.pass:[<span data-type="footnote" id="workers">Workers are a way of executing background tasks in browsers. The initiator can communicate with their <a href="https://mjavascript.com/out/workers">workers</a>, which run in a different execution context, via messaging.</span>] Each of these execution contexts has its own global object. Global variables defined on the `window` object of a page, for example, aren't available to a `ServiceWorker`. In contrast, the global symbol registry is shared across all code realms.

There are two methods that interact with the runtime-wide global symbol registry: `Symbol.for` and `Symbol.keyFor`. What do they do?

===== Getting symbols with Symbol.for(key)

The `Symbol.for(key)` ((("symbols", "Symbol.for(key)")))method looks up `key` in the runtime-wide symbol registry. If a symbol with the provided `key` exists in the global registry, that symbol is returned. If no symbol with that `key` is found in the registry, one is created and added to the registry under the provided `key`. That's to say, `Symbol.for(key)` is idempotent: it looks for a symbol under a `key`, creates one if it didn't already exist, and then returns the symbol.

In the following code snippet, the first call to `Symbol.for` creates a symbol identified as `'example'`, adds it to the registry, and returns it. The second call returns that same symbol because the `key` is already in the registry--and associated to the symbol returned by the first call.

[source,javascript]
----
const example = Symbol.for('example')
console.log(example === Symbol.for('example'))
// <- true
----

The global symbol registry keeps track of symbols by their `key`. Note that the `key` will also be used as a `description` when the symbols that go into the registry are created. Considering these symbols are global on a runtime-wide level, you might want to prefix symbol keys in the global registry with a value that identifies your library or component, mitigating potential name clashes.

===== Using Symbol.keyFor(symbol) to retrieve symbol keys

Given a ((("symbols", "Symbol.keyFor(symbol)")))symbol `symbol`, `Symbol.keyFor(symbol)` returns the `key` that was associated with `symbol` when the symbol was added to the global registry. The next example shows how we can grab the `key` for a `symbol` using `Symbol.keyFor`.

[source,javascript]
----
const example = Symbol.for('example')
console.log(Symbol.keyFor(example))
// <- 'example'
----

Note that if the symbol isn't in the global runtime registry, then the method returns `undefined`.

[source,javascript]
----
console.log(Symbol.keyFor(Symbol()))
// <- undefined
----

Also keep in mind that it's not possible to match symbols in the global registry using local symbols, even when they share the same description. The reason for that is that local symbols aren't part of the global registry, as shown in the following piece of code.

[source,javascript]
----
const example = Symbol.for('example')
console.log(Symbol.keyFor(Symbol('example')))
// <- undefined
----

Now that you've learned about the API for interacting with the global symbol registry, let's take some considerations into account.

===== Best practices and considerations

A runtime-wide registry means the symbols are accessible across code realms. The global registry returns a reference to the same object in any realm the code runs in. In the following example, we demonstrate how the `Symbol.for` API returns the same symbol in a page and within an `<iframe>`.

[source,javascript]
----
const d = document
const frame = d.body.appendChild(d.createElement('iframe'))
const framed = frame.contentWindow
const s1 = window.Symbol.for('example')
const s2 = framed.Symbol.for('example')
console.log(s1 === s2)
// <- true
----

There are trade-offs in using widely available symbols. On the one hand, they make it easy for libraries to expose their own symbols, but on the other hand they could also expose their symbols on their own API, using local symbols. The symbol registry is obviously useful when symbols need to be shared across any two code realms; for example, `ServiceWorker` and a web page. The API is also convenient when you don't want to bother storing references to the symbols. You could use the registry directly for that, since every call with a given `key` is guaranteed to return the same `symbol`. You'll have to keep in mind, though, that these symbols are shared across the runtime and that might lead to unwanted consequences if you use generic symbol names ((("symbols", "global symbol registry", startref="sym3gsr")))((("global symbol registry", startref="gsr3")))like `each` or `contains`.

There's one more kind of symbol: built-in well-known symbols.

==== Well-Known Symbols

So ((("symbols", "well-known", id="sym3wk")))far we've covered symbols you can create using the `Symbol` function and those you can create through `Symbol.for`. The third and last kind of symbols we're going to cover are the well-known symbols. These are built into the language instead of created by JavaScript developers, and they provide hooks into internal language behavior, allowing you to extend or customize aspects of the language that weren't accessible prior to ES6.

A great example of how symbols can add extensibility to the language without breaking existing code is the `Symbol.toPrimitive` ((("symbols", "  Symbol.toPrimitive")))well-known symbol. It can be assigned a function to determine how an object is cast into a primitive value. The function receives a `hint` parameter that can be `'string'`, `'number'`, or `'default'`, indicating what type of primitive value is expected.

[source,javascript]
----
const morphling = {
  [Symbol.toPrimitive](hint) {
    if (hint === 'number') {
      return Infinity
    }
    if (hint === 'string') {
      return 'a lot'
    }
    return '[object Morphling]'
  }
}
console.log(+morphling)
// <- Infinity
console.log(`That is ${ morphling }!`)
// <- 'That is a lot!'
console.log(morphling + ' is powerful')
// <- '[object Morphling] is powerful'
----

Another example of a well-known symbol is `Symbol.match`. A ((("symbols", "Symbol.match")))regular expression that sets `Symbol.match` to `false` will be treated as a string literal when passed to `.startsWith`, `.endsWith`, or `.includes`. These (((".startsWith()", primary-sortas="startsWith")))(((".endsWith()", primary-sortas="endsWith")))(((".includes()", primary-sortas="includes")))(((".startsWith()")))(((".endsWith()")))(((".includes()")))three functions are new string methods in ES6. First we have `.startsWith`, which can be used to determine if the string starts with another string. Then there's `.endsWith`, which finds out whether the string ends in another one. Lastly, the `.includes` method returns `true` if a string contains another one. The next snippet of code shows how `Symbol.match` can be used to compare a string with the string representation of a regular expression.

[source,javascript]
----
const text = '/an example string/'
const regex = /an example string/
regex[Symbol.match] = false
console.log(text.startsWith(regex))
// <- true
----

If the regular expression wasn't modified through the symbol, it would've thrown because the `.startsWith` method expects a string instead of a regular expression.

===== Shared across realms but not in the registry

Well-known symbols ((("symbols", "Symbol.iterator")))are shared across realms. The following example shows how `Symbol.iterator` is the same reference as that within the context of an `<iframe>` window.

[source,javascript]
----
const frame = document.createElement('iframe')
document.body.appendChild(frame)
Symbol.iterator === frame.contentWindow.Symbol.iterator
// <- true
----

Note that even though well-known symbols are shared across code realms, they're not in the global registry. The following bit of code shows that `Symbol.iterator` produces `undefined` when we ask for its `key` in the registry. That means the symbol isn't listed in the global registry.

[source,javascript]
----
console.log(Symbol.keyFor(Symbol.iterator))
// <- undefined
----

One of the most useful well-known symbols is `Symbol.iterator`, used by a few different language constructs to iterate over a sequence, as defined by a function assigned to a property using that symbol on any object. In the next chapter we'll go over `Symbol.iterator` in detail, using it extensively along with the iterator and iterable ((("symbols", startref="sym3")))((("symbols", "well-known", startref="sym3wk")))protocols.

=== Object Built-in Improvements

While ((("objects", "built-in improvements", id="ob3bii")))we've already addressed syntax enhancements coming to object literals in <<es6-essentials>>, there are a few new static methods available to the `Object` built-in that we haven't addressed yet. It's time to take a look at what these methods bring to the table.

We've already looked at `Object.getOwnPropertySymbols`, but let's also take a look at `Object.assign`, `Object.is`, and `Object.setPrototypeOf`.

[[extending_objects_with_object_assign]]
==== Extending Objects with Object.assign

The ((("objects", "extending", id="ob3e")))((("Object.assign", id="obass3")))need to provide default values for a configuration object is not at all uncommon. Typically, libraries and well-designed component interfaces come with sensible defaults that cater to the most frequented use cases.

A Markdown library, for example, might convert Markdown into HTML by providing only an `input` parameter. That's its most common use case, simply parsing Markdown, and so the library doesn't demand that the consumer provides any options. The library might, however, support many different options that could be used to tweak its parsing behavior. It could have an option to allow `<script>` or `<iframe>` tags, or an option to highlight keywords in code snippets using CSS.

Imagine, for example, that you want to provide a set of defaults like the one shown next.

[source,javascript]
----
const defaults = {
  scripts: false,
  iframes: false,
  highlightSyntax: true
}
----

One possibility would be to use the `defaults` object as the default value for the `options` parameter, using destructuring. In this case, the users must provide values for every option whenever they decide to provide any options at all.

[source,javascript]
----
function md(input, options=defaults) {
}
----

The default values have to be merged with user-provided configuration, somehow. That's where `Object.assign` comes in, as shown in the following example. We start with an empty `{}` object--which will be mutated and returned by ++Object.assign++—we copy the default values over to it, and then copy the options on top. The resulting `config` object will have all of the default values plus the user-provided configuration.

[source,javascript]
----
function md(input, options) {
  const config = Object.assign({}, defaults, options)
}
----

.Understanding the Target of Object.assign
****
The `Object.assign` function mutates its first argument. Its signature is `(target, ...sources)`. Every source is applied onto the target object, source by source and property by property.

Consider the following scenario, where we don't pass an empty object as the first argument of `Object.assign`, instead just providing it with the `defaults` and the `options`. We would be changing the contents of the `defaults` object, losing some of our default values--and obtaining some wrong ones--in the process of mutating the object. The first invocation would produce the same result as the previous example, but it would modify our defaults in the process, changing how subsequent calls to `md` work.

[source,javascript]
----
function md(input, options) {
  const config = Object.assign(defaults, options)
}
----

For this reason, it's generally best to pass a brand new object on the first position, every time.
****

For any properties that had a default value where the user also provided a value, the user-provided value will prevail. Here's how `Object.assign` works. First, it takes the first argument passed to it; let's call it `target`. It then iterates over all keys of each of the other arguments; let's call them `sources`. For each source in `sources`, all of its properties are iterated and assigned to `target`. The end result is that rightmost sources--in our case, the `options` object--overwrite any previously assigned values, as shown in the following bit of code.

[source,javascript]
----
const defaults = {
  first: 'first',
  second: 'second'
}
function applyDefaults(options) {
  return Object.assign({}, defaults, options)
}
applyDefaults()
// <- { first: 'first', second: 'second' }
applyDefaults({ third: 3 })
// <- { first: 'first', second: 'second', third: 3 }
applyDefaults({ second: false })
// <- { first: 'first', second: false }
----

Before `Object.assign` made its way into the language, there were numerous similar implementations of this technique in user-land JavaScript, with names like assign, or extend. Adding `Object.assign` to the language consolidates these options into a single method.

Note that `Object.assign` takes into consideration only own enumerable properties, including both string and symbol properties.

[source,javascript]
----
const defaults = {
  [Symbol('currency')]: 'USD'
}
const options = {
  price: '0.99'
}
Object.defineProperty(options, 'name', {
  value: 'Espresso Shot',
  enumerable: false
})
console.log(Object.assign({}, defaults, options))
// <- { [Symbol('currency')]: 'USD', price: '0.99' }
----

Note, however, that `Object.assign` doesn't cater to every need. While most user-land implementations have the ability to perform deep assignment, `Object.assign` doesn't offer a recursive treatment of objects. Object values are assigned as properties on `target` directly, instead of being recursively assigned key by key.

In the following bit of code you might expect the `f` property to be added to `target.a` while keeping `a.b` and `a.d` intact, but the `a.b` and `a.d` properties are lost when using `Object.assign`.

[source,javascript]
----
Object.assign({}, { a: { b: 'c', d: 'e' } }, { a: { f: 'g' } })
// <- { a: { f: 'g' } }
----

In the same vein, arrays don't get any special treatment either. If you expected recursive behavior in `Object.assign` the following snippet of code may also come as a surprise, where you may have expected the resulting object to have `'d'` in the third position of the array.

[source,javascript]
----
Object.assign({}, { a: ['b', 'c', 'd'] }, { a: ['e', 'f'] })
// <- { a: ['e', 'f'] }
----

At the time of this writing, there's an ECMAScript stage 3 proposalpass:[<span data-type="footnote" id="object-spread">You can find the proposal draft at <a href="https://mjavascript.com/out/object-spread">GitHub</a>.</span>] to implement spread in objects, similar to how you can spread iterable objects onto an array in ES6. Spreading an ((("objects", "object spread")))object onto another is equivalent to using an `Object.assign` function call.

The following piece of code shows a few cases where we're spreading the properties of an object onto another one, and their `Object.assign` counterpart. As you can see, using object spread is more succinct and should be preferred where possible.

[source,javascript]
----
const grocery = { ...details }
// Object.assign({}, details)
const grocery = { type: 'fruit', ...details }
// Object.assign({ type: 'fruit' }, details)
const grocery = { type: 'fruit', ...details, ...fruit }
// Object.assign({ type: 'fruit' }, details, fruit)
const grocery = { type: 'fruit', ...details, color: 'red' }
// Object.assign({ type: 'fruit' }, details, { color: 'red' })
----

As a counterpart to object spread, the proposal includes object rest properties, which is similar to the array rest pattern. We can use object rest whenever we're destructuring an object.

The following example shows how we could leverage ((("objects", "object rest")))object rest to get an object containing only properties that we haven't explicitly named in the parameter list. Note that the object rest property must be in the last position of destructuring, just like the array rest pattern.

[source,javascript]
----
const getUnknownProperties = ({ name, type, ...unknown }) =>
  unknown
getUnknownProperties({
  name: 'Carrot',
  type: 'vegetable',
  color: 'orange'
})
// <- { color: 'orange' }
----

We could take a similar approach when destructuring an object in a variable declaration statement. In the next example, every property that's not explicitly destructured is placed in a `meta` object.

[source,javascript]
----
const { name, type, ...meta } = {
  name: 'Carrot',
  type: 'vegetable',
  color: 'orange'
}
// <- name = 'Carrot'
// <- type = 'vegetable'
// <- meta = { color: 'orange' }
----

We dive deeper into object rest and ((("objects", "extending", startref="ob3e")))((("Object.assign", startref="obass3")))spread in <<practical-considerations>>.

==== Comparing Objects with Object.is

The `Object.is` ((("objects", "comparing", id="ob3c")))((("Object.is", id="obis3")))method is a slightly different version of the strict equality comparison operator, `===`. For the most part, `Object.is(a, b)` is equal to `a === b`. There are two differences: the case of `NaN` and the case of `-0` and `+0`. This algorithm is referred to ((("  SameValue")))as `SameValue` in the ECMAScript specification.

When `NaN` is compared to `NaN`, ((("NaN")))the strict equality comparison operator returns `false` because `NaN` is not equal to itself. The `Object.is` method, however, returns `true` in this special case.

[source,javascript]
----
NaN === NaN
// <- false
Object.is(NaN, NaN)
// <- true
----

Similarly, when `-0` is compared to `+0`, the `===` operator produces `true` while `Object.is` returns `false`.

[source,javascript]
----
-0 === +0
// <- true
Object.is(-0, +0)
// <- false
----

These differences may not seem like much, but dealing with `NaN` has always been cumbersome because of its special quirks, such as `typeof NaN` being `'number'` and it not being equal to itself.

==== Object.setPrototypeOf

The `Object.setPrototypeOf` method ((("objects", "setting prototypes", id="ob3sp")))((("Object.setPrototypeOf", id="ospo3")))does exactly what its name conveys: it sets the prototype of an object to a reference to another object. It's considered the proper way of setting the prototype, as opposed to using `__proto__`, which is a legacy feature.

Before ES6, we were introduced ((("Object.create()")))to `Object.create` in ES5. Using that method, we could create an object based on any prototype passed into `Object.create`, as shown next.

[source,javascript]
----
const baseCat = { type: 'cat', legs: 4 }
const cat = Object.create(baseCat)
cat.name = 'Milanesita'
----

The `Object.create` method is, however, limited to newly created objects. In contrast, we could use `Object.setPrototypeOf` to change the prototype of an object that already exists, as shown in the following code snippet.

[source,javascript]
----
const baseCat = { type: 'cat', legs: 4 }
const cat = Object.setPrototypeOf(
  { name: 'Milanesita' },
  baseCat
)
----

Note however that there are serious performance implications when using `Object.setPrototypeOf` as opposed to `Object.create`, and some careful consideration is in order before you decide to go ahead and sprinkle `Object.setPrototypeOf` all over a codebase.

.Performance Issues
****
Using `Object.setPrototypeOf` to change the prototype of an object is an expensive operation. Here is what the Mozilla Developer Network documentation has to say about the matter:

[quote, Mozilla Developer Network]
____
Changing the prototype of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in a `Object.setPrototypeOf(…)` statement, but may extend to any code that has access to any object whose prototype has been altered. If you care about performance you should avoid setting the prototype of an object. Instead, create a new ((("objects", "built-in improvements", startref="ob3bii")))object with the desired ((("objects", "setting prototypes", startref="ob3sp")))((("Object.setPrototypeOf", startref="ospo3")))prototype using `Object.create()`.
____

****

=== Decorators

Decorators are, ((("Decorators", id="dec3")))as most things programming, definitely not a new concept. The pattern is fairly commonplace in modern programming languages: you have _attributes_ in C#, they're called _annotations_ in Java, there are _decorators_ in Python, and the list goes on. There's a JavaScript decorators proposalpass:[<span data-type="footnote" id="decorators"> in the works and you can find the draft online at <a href="https://mjavascript.com/out/decorators">GitHub</a>.</span>] It is currently sitting at stage 2 of the TC39 process.

==== A Primer on JavaScript Decorators

The syntax for JavaScript decorators is fairly similar to that of Python decorators. JavaScript decorators may be applied to classes and any statically defined properties, such as those found on an object literal declaration or in a `class` declaration--even if they are `get` accessors, `set` accessors, or `static` properties.

The proposal defines a _decorator_ as an `@` followed by a sequence of dotted identifiersfootnoteref:[no-dynamic-access, Accessing properties via `[]` notation is disallowed due to the difficulty it would present when disambiguating grammar at the compiler level.] and an optional argument list. Here are a few examples:

- `@decorators.frozen` is a valid decorator
- `@decorators.frozen(true)` is a valid decorator
- `@decorators().frozen()` is a syntax error
- `@decorators['frozen']` is a syntax error

Zero or more decorators can be attached to `class` declarations and class members.

[source,javascript]
----
@inanimate
class Car {}

@expensive
@speed('fast')
class Lamborghini extends Car {}

class View {
  @throttle(200) // reconcile once every 200ms at most
  reconcile() {}
}
----

Decorators are implemented by way of functions. Member decorator functions take a member ((("Decorators", "descriptors in", id="dec3d")))((("descriptors", id="d3")))descriptor and return a member descriptor. Member descriptors are similar to property descriptors, but with a different shape. The following bit of code has the member descriptor interface, as defined by the decorators proposal. An optional `finisher` function receives the class constructor, allowing us to perform operations related to the class whose property is being decorated.

----
interface MemberDescriptor {
  kind: "Property"
  key: string,
  isStatic: boolean,
  descriptor: PropertyDescriptor,
  extras?: MemberDescriptor[]
  finisher?: (constructor): void;
}
----

In the following example we define a `readonly` member decorator function that makes decorated members nonwritable. Taking advantage of the object rest parameter and object spread, we modify the property descriptor to be non-writable while keeping the rest of the member descriptor unchanged.

[source,javascript]
----
function readonly({ descriptor, ...rest }) {
  return {
    ...rest,
    descriptor: {
      ...descriptor,
      writable: false
    }
  }
}
----

Class decorator functions take a `ctor`, which is the class constructor being decorated; a `heritage` parameter, containing the parent class when the decorated class extends another class; and a `members` array, with a list of member descriptors for the class being decorated.

We could implement a class-wide `readonlyMembers` decorator by reusing the `readonly` member decorator on each member descriptor for a decorated class, as shown next.

[source,javascript]
----
function readonlyMembers(ctor, heritage, members) {
  return members.map(member => readonly(member))
}
----

==== Stacking Decorators and a Warning About Immutability

With all ((("Decorators", "stacking")))the fluff around immutability you may be tempted to return a new property descriptor from your decorators, without modifying the original descriptor. While well-intentioned, this may have an undesired effect, as it is possible to decorate the same `class` or class member several times.

If any decorators in a piece of code returned an entirely new `descriptor` without taking into consideration the `descriptor` parameter they receive, they'd effectively lose all the decoration that took place before the different descriptor was returned.

We should be careful to write decorators that take into account the supplied `descriptor`. Always create one that's based on the original `descriptor` that's provided as a ((("Decorators", "descriptors in", startref="dec3d")))((("descriptors", startref="d3")))parameter.

==== Use Case By Example: Attributes in C#

A long time ago, ((("Decorators", "versus C# attributes", secondary-sortas="c", id="dec3vca")))I was first getting acquainted with C# by way of an Ultima Onlinefootnoteref:[uo,Ultima Online is a decades-old fantasy role playing game based on the Ultima universe.] server emulator written in open source C# code--RunUO. ((("RunUO", id="ruo3")))RunUO was one of the most beautiful codebases I've ever worked with, and it was written in C# to boot.

They distributed the server software as an executable and a series of `.cs` files. The `runuo` executable would compile those `.cs` scripts at runtime and dynamically mix them into the application. The result was that you didn't need the Visual Studio IDE (nor `msbuild`), or anything other than just enough programming knowledge to edit one of the "scripts" in those `.cs` files. All of the above made RunUO the perfect learning environment for the new developer.

RunUO relied heavily on reflection. RunUO's developers made significant efforts to make it customizable by players who were not necessarily invested in programming, but were nevertheless interested in changing a few details of the game, such as how much damage a dragon's fire breath inflicts or how often it shot fireballs. Great developer experience was a big part of their philosophy, and you could create a new kind of `Dragon` just by copying one of the monster files, changing it to inherit from the `Dragon` class, and overriding a few properties to change its color hue, its damage output, and so on.

Just as they made it easy to create new monsters--or "non-player characters" (_NPC_ in gaming slang)--they also relied on reflection to provide functionality to in-game administrators. Administrators could run an in-game command and click on an item or a monster to visualize or change properties without ever leaving the game.

[[fig0301]]
.Modifying properties for a RunUO item in-game from the Ultima Online client
image::images/pmjs_0301.png["Modifying properties for a RunUO item in-game from the Ultima Online client."]

Not every property in a class is meant to be accessible in-game, though. Some properties are only meant for internal use, or not meant to be modified at runtime. RunUO had a `CommandPropertyAttribute` decorator,pass:[<span data-type="footnote" id="runuo-attributes">The RunUO Git repository has the definition of <a href="https://mjavascript.com/out/runuo-attributes"><code>CommandPropertyAttribute</code> for RunUO</a>.</span>] which defined that the property could be modified in-game and let you also specify the access level required to read and write that property. This decorator was used extensively throughout the RunUO codebase.pass:[<span data-type="footnote" id="runuo-commandprops">Its use is widespread throughout the codebase, marking over 200 properties in the <a href="https://mjavascript.com/out/runuo-commandprops">RunUO core alone</a>.</span>]

The `PlayerMobile` class, which governed how a player's character works, is a great place to look at these attributes. `PlayerMobile` has several properties that are accessible in-gamepass:[<span data-type="footnote" id="runuo-playermobile">You can find quite a few usage examples of the <code>CommandProperty</code> attribute in the <a href="https://mjavascript.com/out/runuo-playermobile"><code>PlayerMobile.cs</code> class</a>.</span>] to administrators and moderators. Here are a couple of getters and setters, but only the first one has the `CommandProperty` attribute--making that property accessible to Game Masters in-game.

[source,csharp]
----
[CommandProperty(AccessLevel.GameMaster)]
public int Profession
{
  get{ return m_Profession }
  set{ m_Profession = value }
}

public int StepsTaken
{
  get{ return m_StepsTaken }
  set{ m_StepsTaken = value }
}
----

One interesting difference between C# attributes and JavaScript decorators is that reflection in C# allows us to pull all custom attributes from an object using `MemberInfo#getCustomAttributes`. RunUO leverages that method to pull up information about each property that should be accessible in-game when displaying the dialog that lets an administrator view or modify an in-game object's ((("RunUO", startref="ruo3")))((("Decorators", "versus C# attributes", secondary-sortas="c", startref="dec3vca")))properties.

==== Marking Properties in JavaScript

In ((("Decorators", "and marking properties", secondary-sortas="marking", id="dec3amp")))JavaScript, there's no such thing--not in the existing proposal draft, at least--to get the custom attributes on a property. That said, JavaScript is a highly dynamic language, and creating this sort of "labels" wouldn't be much of a hassle. Decorating a `Dog` with a "command property" wouldn't be all that different from RunUO and C#.

[source,javascript]
----
class Dog {
  @commandProperty('game-master')
  name;
}
----

The `commandProperty` function would need to be a little more sophisticated than its C# counterpart. Given that there is no reflection around JavaScript decoratorsfootnote:[Reflection around JavaScript decorators is not being considered for JavaScript at this time, as it'd involve engines keeping more metadata in memory. We can, however, use symbols and lists to get around the need for native reflection.], we could use a runtime-wide symbol to keep around an array of command properties for any given class.

[source,javascript]
----
function commandProperty(writeLevel, readLevel = writeLevel) {
  return ({ key, ...rest }) => ({
    key,
    ...rest,
    finisher(ctor) {
      const symbol = Symbol.for('commandProperties')
      const commandPropertyDescriptor = {
        key,
        readLevel,
        writeLevel
      }
      if (!ctor[symbol]) {
        ctor[symbol] = []
      }
      ctor[symbol].push(commandPropertyDescriptor)
    }
  })
}
----

A `Dog` class could have as many command properties as we deemed necessary, and each would be listed behind a symbol property. To find the command properties for any given class, all we'd have to do is use the following function, which retrieves a list of command properties from the symbol property, and offers a default value of +[]+. We always return a copy of the original list to prevent consumers from accidentally making changes to it.

[source,javascript]
----
function getCommandProperties(ctor) {
  const symbol = Symbol.for('commandProperties')
  const properties = ctor[symbol] || []
  return [...properties]
}
getCommandProperties(Dog)
// <- [{ key: 'name', readLevel: 'game-master',
// writeLevel: 'game-master' }]
----

We could then iterate over known safe command properties and render a way of modifying those during runtime, through a simple UI. Instead of maintaining long lists of properties that can be modified, relying on some sort of heuristics bound to break from time to time, or using some sort of restrictive naming convention, decorators are the cleanliest way to implement a protocol where we mark properties as special for some particular use ((("Decorators", "and marking properties", secondary-sortas="marking", startref="dec3amp")))case.

In the following chapter we'll look at more features coming in ES6 and how they can be used to iterate over any JavaScript objects, as well as how to master flow control using promises and ((("Decorators", startref="dec3")))generators.
