Symbol Type
Objects the Basics: Symbol Type
What are the two types of object property keys in JavaScript?
View Answer:
Can you explain what a Symbol is in JavaScript?
View Answer:
let sym1 = Symbol();
let sym2 = Symbol('foo');
let sym3 = Symbol('foo');
Symbol('foo') === Symbol('foo'); // false, Symbol returns a unique
Does the Symbol function get registered in the global symbol registry?
View Answer:
Can two Symbol descriptions be identical in JavaScript?
View Answer:
let id1 = Symbol('id');
let id2 = Symbol('id');
console.log(id1 == id2); // false
console.log(id1.description === id2.description); // true
The description can be identical, but the value is unique and returns false if both values get compared.
Do Symbols auto-convert to strings in JavaScript?
View Answer:
let id = Symbol('id');
console.log(id); // TypeError: Cannot convert a Symbol value to a string
// Solution
let id = Symbol('id');
console.log(id.toString()); // Symbol(id), now it works
The intentional "language guard" prevents unintended conversions between strings and symbols, as they are fundamentally different. This behavior serves to avoid accidental mistakes and ensures the appropriate handling of strings and symbols.
To explicitly convert a Symbol to a string, what built-in method should we use?
View Answer:
let id = Symbol('id');
console.log(id.toString()); // Symbol(id), now it works
If you want to show the Symbol description, what property should you use?
View Answer:
let id = Symbol('id');
console.log(id.description); // returns id
How can the Symbol object act as a property safeguard in objects?
View Answer:
let user = { // belongs to another code
name: "John"
};
let id = Symbol("id");
user[id] = 1;
console.log( user[id] ); // we can access the data using the symbol as the key
What is the benefit of using Symbol("id") over a string "id"?
View Answer:
// ...
let id = Symbol('id');
user[id] = 'Their id value';
let user = { name: 'John' };
// Our script uses "id" property
user.id = 'Our id value';
// ...Another script also wants "id" for its purposes...
user.id = 'Their id value';
// Boom! overwritten by another script!
Can you use a Symbol in an object literal?
View Answer:
// Creating a Symbol
const mySymbol = Symbol('mySymbol');
// Using Symbol as a property key in an object literal
const obj = {
[mySymbol]: 'Value associated with Symbol'
};
// Accessing the property using the Symbol
console.log(obj[mySymbol]); // Output: Value associated with Symbol
How do you check if a property is a Symbol in a JavaScript object?
View Answer:
const obj = {
prop1: 'Value 1',
prop2: Symbol('mySymbol')
};
console.log(typeof obj.prop1 === 'symbol'); // false
console.log(typeof obj.prop2 === 'symbol'); // true
Can you return a Symbol in a for…in loop?
View Answer:
let id = Symbol('id');
let user = {
name: 'John',
age: 30,
[id]: 123,
};
for (let key in user) console.log(key); // name, age (no symbols)
// the direct access by the symbol works
console.log('Direct: ' + user[id]);
JavaScript hides Symbol properties for a reason. Is there a way to copy all the properties, including the symbolic ones?
View Answer:
const obj = {};
const localA = Symbol("a");
const globalB = Symbol.for("b");
obj[localA] = "localSymbol";
obj[globalB] = "globalSymbol";
const objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols.length); // 2
console.log(objectSymbols); // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]); // Symbol(a)
// Using Object.assign()
let id = Symbol('id');
let user = {
[id]: 123,
};
let clone = Object.assign({}, user);
console.log(clone[id]); // 123
Is there a way to access or create a symbol from the registry to ensure that symbols with the same name refer to the same entity in JavaScript?
View Answer:
// read from the global registry
let id = Symbol.for('id'); // if the symbol did not exist, it is created
// read it again (maybe from another part of the code)
let idAgain = Symbol.for('id');
// the same symbol
console.log(id === idAgain); // true
What is the difference between Symbol.for(key) and Symbol.keyFor(sym)?
View Answer:
// get symbol by name
let sym = Symbol.for('name');
let sym2 = Symbol.for('id');
// get name by symbol
console.log(Symbol.keyFor(sym)); // name
console.log(Symbol.keyFor(sym2)); // id
The Symbol.keyFor internally uses the global symbol registry to look up the key for the symbol. Does it work for non-global symbols?
View Answer:
let globalSymbol = Symbol.for('name');
let localSymbol = Symbol('name');
console.log(Symbol.keyFor(globalSymbol)); // name, global symbol
console.log(Symbol.keyFor(localSymbol)); // undefined, not global
console.log(localSymbol.description); // name
Can you use the Symbol type to create private properties in Classes?
View Answer:
let privateProperty = Symbol();
class MyClass {
constructor() {
this[privateProperty] = 'private';
}
checkPrivate() {
return this[privateProperty];
}
}
let instance = new MyClass();
console.log(instance.checkPrivate()); // 'private'
console.log(instance.privateProperty); // undefined
In the above example, the privateProperty
variable is a unique symbol that is used as the key for a property in the MyClass
object. This property can't be accessed outside of the object except through a method defined in the class (like the checkPrivate
method in this case).
However, do note that even though it acts like a private property, it's not completely private. You can still access it if you have a reference to the Symbol or by using the Object.getOwnPropertySymbols()
method:
let privateSymbols = Object.getOwnPropertySymbols(instance);
console.log(instance[privateSymbols[0]]); // 'private'
If you want true private fields, you can use the private field syntax (#
) in JavaScript classes (introduced in ECMAScript 2020). These are only accessible inside the class they are defined:
class MyClass {
#privateField;
constructor() {
this.#privateField = 'private';
}
checkPrivate() {
return this.#privateField;
}
}
let instance = new MyClass();
console.log(instance.checkPrivate()); // 'private'
console.log(instance.privateField); // undefined
In this example, #privateField
is truly private and can't be accessed from outside the class.