Chapter 8: Chapter 8. Controlling access to objects
The introduction explains why changing JavaScript objects may need monitoring and identifies getters, setters, and proxies as ways to control access.
After this chapter you will be able to
- Dynamic objects and monitoring. Explain why JavaScript objects may need monitoring: properties can be added, changed, or removed, and applications may need to observe those changes for tasks such as validation, logging, or displaying data.
- Controlled access to property values. Explain how making skillLevel accessible only through getSkillLevel and setSkillLevel lets code respond to reads and writes, such as by logging, validating values, or updating the UI.
- Built-in property accessor advantage. Distinguish explicit getSkillLevel and setSkillLevel calls from built-in getters and setters, which are accessed with normal property syntax while running methods that can compute or validate values.
- Property access through methods. Explain that reading a property with a getter implicitly calls its getter, while assigning to a property with a setter implicitly calls its setter, even though both operations use ordinary property syntax.
- Closure-backed property access. Explain why the section uses Object.defineProperty inside the Ninja constructor to expose skillLevel while keeping _skillLevel in a closure rather than directly on the object.
- Setter validation of assignments. Explain how the skillLevel setter validates an assignment: it accepts an integer and updates _skillLevel, but throws an exception for a non-integer and leaves _skillLevel unchanged. Describe why this can prevent wrong-type bugs despite adding overhead.
- Computed property access. Explain how reading and writing the shogun object's computed fullTitle property use its name and clan properties.
- Proxy access versus getters. Explain how a proxy acts as a surrogate for a target object and how its scope differs from a getter or setter for one property.
- Proxy construction and property traps. Trace how the Proxy constructor and its get and set traps affect reads and writes in the emperor example, distinguishing access through the proxy from access directly through the target.
- Proxy-based property access logging. Trace how makeLoggable wraps a target object in a proxy whose get and set traps log property reads and writes while performing those operations.
- Proxy-based function timing. Trace how a proxy measures the execution time of isPrime while preserving its behavior and leaving existing calls unchanged.
- Autopopulated folder properties. Explain how a proxy’s get trap handles access to existing and missing folder properties, and why this lets code traverse a previously undefined nested path.
- Proxy index translation. Trace how the array proxy handles reads and writes using negative indexes while preserving ordinary nonnegative indexing.
- Proxy access overhead. Explain why controlling access through a proxy can make operations slower than accessing an object directly.
- Array access timing comparison. Describe how the section compares access through a proxy with access to a standard array.
- Performance-sensitive proxy use. Explain what the reported timing results imply for deciding when to use proxies.
What it builds on
- Side effects of the dynamic nature of JavaScript (chapter 7) · The dynamic nature of JavaScript objects.
- Mimicking private variables (chapter 5) · Closures can mimic private variables.
Section by section
Introduction
The introduction explains why changing JavaScript objects may need monitoring and identifies getters, setters, and proxies as ways to control access.
- Dynamic objects and monitoring: Explain why JavaScript objects may need monitoring: properties can be added, changed, or removed, and applications may need to observe those changes for tasks such as validation, logging, or displaying data.
Why it matters: Monitoring helps you respond when an object's properties change. - Access control approaches: Distinguish the roles introduced here: getters and setters control access to specific object properties, while proxies are ES6 objects that control access to other objects.
Why it matters: This distinction gives you a starting point for the chapter's two approaches to access control.
Key terms: dynamic collections of properties, monitor, getters and setters, proxies, ES6
8.1 Controlling access to properties with getters and setters
This section explains why controlling access to object properties is useful and contrasts explicit accessor methods with JavaScript’s built-in getters and setters.
- Controlled access to property values: Explain how making skillLevel accessible only through getSkillLevel and setSkillLevel lets code respond to reads and writes, such as by logging, validating values, or updating the UI.
Why it matters: Routing access through methods gives you a place to check or respond to property use. - Built-in property accessor advantage: Distinguish explicit getSkillLevel and setSkillLevel calls from built-in getters and setters, which are accessed with normal property syntax while running methods that can compute or validate values.
Why it matters: Built-in accessors offer controlled access without requiring callers to use explicit method calls.
Key terms: private skillLevel variable, getSkillLevel, setSkillLevel, closures, value property, true getters and setters, normal data properties
8.1 Do you know?
This section poses self-check questions about getters, setters, and proxies without explaining the answers.
8.1.1 Defining getters and setters
This section shows how to define getters and setters and how they make ordinary-looking property reads and writes execute methods, including methods that access a closure-held variable.
- Property access through methods: Explain that reading a property with a getter implicitly calls its getter, while assigning to a property with a setter implicitly calls its setter, even though both operations use ordinary property syntax.
Why it matters: It explains why an apparently simple property access can run code. - Getter and setter definitions: Describe the two ways this section defines getters and setters: with get and set prefixes in object literals or ES6 classes, or with get and set methods in an Object.defineProperty descriptor.
Why it matters: These forms let you recognize where a property's read and write behavior is defined. - Closure-backed property access: Explain why the section uses Object.defineProperty inside the Ninja constructor to expose skillLevel while keeping _skillLevel in a closure rather than directly on the object.
Why it matters: It shows how a normal-looking property can provide access to a variable held outside the object's directly accessible properties. - Getter-only assignment behavior: Distinguish what happens when code assigns to a property that has a getter but no setter in nonstrict versus strict mode.
Why it matters: It prevents a getter-only property from being mistaken for one that can be updated normally.
Key terms: getter, setter, property, object literals, ES6 classes, get, set, Object.defineProperty, property descriptor, closure
8.1.2 Using getters and setters to validate property values
This section shows how a setter can reject invalid property assignments before they change a private value.
- Setter validation of assignments: Explain how the skillLevel setter validates an assignment: it accepts an integer and updates _skillLevel, but throws an exception for a non-integer and leaves _skillLevel unchanged. Describe why this can prevent wrong-type bugs despite adding overhead.
Why it matters: Validating at the setter helps keep an invalid value out of the property’s underlying state.
Key terms: setter, skillLevel, private _skillLevel variable, integer, exception
8.1.3 Using getters and setters to define computed properties
Explains how getters and setters make a property reflect other properties without storing its own value, and why that can make code clearer.
- Computed property access: Explain how reading and writing the shogun object's computed fullTitle property use its name and clan properties.
Why it matters: It lets you describe what a property read or write actually does instead of treating the property as stored data. - Property representation rationale: Justify representing a value derived solely from an object's internal state as a computed property rather than a method.
Why it matters: It explains when property syntax can communicate the meaning of a derived value more clearly than a method call.
Key terms: computed properties, getter, setter, fullTitle, name, clan, getFullTitle, internal state
8.2 Using proxies to control access
The section explains how a proxy controls access to a target object through operation-specific traps, demonstrates property reads and writes, and identifies operations that cannot be trapped.
- Proxy access versus getters: Explain how a proxy acts as a surrogate for a target object and how its scope differs from a getter or setter for one property.
Why it matters: This distinction explains why a proxy can control more kinds of access than a property-specific getter or setter. - Proxy construction and property traps: Trace how the Proxy constructor and its get and set traps affect reads and writes in the emperor example, distinguishing access through the proxy from access directly through the target.
Why it matters: The example shows why using the proxy rather than the target changes what happens during ordinary property access. - Limits of trap interception: State which operators the section says proxies cannot trap and explain the stated reasons for excluding equality.
Why it matters: These limits clarify that a proxy does not intercept every JavaScript operation.
Key terms: proxy, target object, getters and setters, Proxy constructor, traps, get trap, set trap, equality, ==, ===
8.2.1 Using proxies for logging
Shows how a proxy can log object-property reads and writes without putting logging code in each property’s getter and setter.
- Proxy-based property access logging: Trace how makeLoggable wraps a target object in a proxy whose get and set traps log property reads and writes while performing those operations.
Why it matters: This lets you trace property access without changing the code for every property. - Centralized logging advantage: Explain why proxy-based logging is cleaner than adding logging to individual property getters and setters in the Ninja example.
Why it matters: Keeping logging separate makes it easier to reuse and less likely to be omitted for a new property.
Key terms: makeLoggable, target object, Proxy, get trap, set trap, getters and setters, domain code, proxy object trap methods
8.2.2 Using proxies for measuring performance
This section shows how a proxy can time function calls without changing the function or its callers.
- Proxy-based function timing: Trace how a proxy measures the execution time of isPrime while preserving its behavior and leaving existing calls unchanged.
Why it matters: You can measure a function’s runtime without editing the function or every place that calls it.
Key terms: proxy, target object, handler, apply trap, console.time, isPrime
8.2.3 Using proxies to autopopulate properties
This section explains how a proxy can create missing folder properties as they are accessed, allowing a nested path to be built without defining each folder beforehand.
- Autopopulated folder properties: Explain how a proxy’s get trap handles access to existing and missing folder properties, and why this lets code traverse a previously undefined nested path.
Why it matters: Creating folders on demand removes repetitive setup and avoids some errors from accessing undefined intermediate properties.
Key terms: proxy, get trap, autopopulating properties, folder object
8.2.4 Using proxies to implement negative array indexes
This section shows how a proxy can give JavaScript arrays negative indexes for reading and writing items from the end.
- Negative index meaning and motivation: Explain what a negative array index means and why a proxy is needed to use one in JavaScript.
Why it matters: It explains both the convenience of negative indexes and why the example uses a proxy. - Proxy index translation: Trace how the array proxy handles reads and writes using negative indexes while preserving ordinary nonnegative indexing.
Why it matters: The same index translation makes negative indexes work for both retrieving and modifying array items.
Key terms: negative array indexes, proxies, proxy, get trap, set trap, unary plus operator, array length
8.2.5 Performance costs of proxies
This section explains why proxies can slow object access, shows how to compare proxied and ordinary array access, and advises where to use proxies cautiously.
- Proxy access overhead: Explain why controlling access through a proxy can make operations slower than accessing an object directly.
Why it matters: A useful proxy feature can carry a cost on every operation that passes through it. - Array access timing comparison: Describe how the section compares access through a proxy with access to a standard array.
Why it matters: Repeating and timing both kinds of access makes the performance cost measurable. - Performance-sensitive proxy use: Explain what the reported timing results imply for deciding when to use proxies.
Why it matters: Whether proxy overhead matters depends on how often the affected code runs.
Key terms: proxy, traps, layer of indirection, proxied array, standard array, new Date().getTime(), proxies, performance sensitive
8.3 Summary
8.4 Exercises
Concepts explained in this chapter
- getterA pair of property accessors that execute custom code when a property is read or assigned.
- setterA property accessor function called when a value is assigned to the property.
- private variableA variable intended to be inaccessible from outside an abstraction boundary, such as an object or function scope.
- Object.definePropertyA JavaScript method that defines or modifies a property on an object with explicit control over its attributes.
- trapA Proxy handler function that intercepts a particular operation on the target object.
- logThe practice of recording useful runtime information to help understand program behavior or diagnose problems.
- negative indexingAn indexing convention that allows arrays to be accessed from the end using negative positions.
- computed propertyA property whose value is derived on access or assignment rather than stored as an independent data field.
- ProxyA JavaScript object that intercepts operations on a target object using a handler.
- get/set trapA collective term for Proxy traps that intercept property reads and writes.
- accessor methodA method used to retrieve or update a property or encapsulated state.
- property descriptorAn object that specifies the attributes and accessors used to define or control a JavaScript property.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
