Skip to main content

Symbol Type

Objects the Basics: Symbol Type



What are the two types of object property keys in JavaScript?

View Answer:
Interview Response: By specification, object property keys may be a string or symbol type. These two types are not numbers, not Booleans, only strings or symbols.

Can you explain what a Symbol is in JavaScript?

View Answer:
Interview Response: A Symbol is a primitive data type in JavaScript that represents a unique identifier, often used to create private object properties and prevent naming collisions.

Technical Response: The data type symbol is a primitive data type. The Symbol() object returns a value of type symbol, and it has static properties that expose several members of built-in objects. It also has static methods that expose the global symbol registry and resembles a built-in object class. A "symbol" represents a unique identifier.

Code Example:

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:
Interview Response: No, the Symbol function is not registered in the global symbol registry. It is a built-in function provided by the language.

Technical Response: No, the Symbol object does not create a global symbol available in your whole codebase. To create symbols available across files and even across realms (each of which has its global scope), use the methods Symbol.for() and Symbol.keyFor() to set and retrieve symbols from the global symbol registry.

Can two Symbol descriptions be identical in JavaScript?

View Answer:
Interview Response: Yes, two Symbol descriptions can be identical in JavaScript only if they refer to the same symbol instance, which is determined by their unique internal Symbol ID.

Code Example:

let id1 = Symbol('id');
let id2 = Symbol('id');

console.log(id1 == id2); // false
console.log(id1.description === id2.description); // true

note

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:
Interview Response: Most values in JavaScript support implicit conversion to a string, but a symbol is rare and unique, it does not auto-convert to a string. You need to explicitly call the toString() method on a Symbol instance to convert it to a string.

Code Example:

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

note

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:
Interview Response: To explicitly convert a Symbol to a string, we can use the toString() method provided by the Symbol prototype object in JavaScript.

Code Example:

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:
Interview Response: To get and show a symbol description, we should use the description property and dot notation to access the value.

Code Example:

let id = Symbol('id');
console.log(id.description); // returns id

How can the Symbol object act as a property safeguard in objects?

View Answer:
Interview Response: The Symbol object can act as a property safeguard in objects by creating unique symbol keys that cannot be accessed or modified by external code, helping to prevent unintended overwriting or interference.

Code Example:

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:
Interview Response: The benefit of using Symbol("id") over a string "id" is that it creates a unique symbol instance that is guaranteed to be globally unique, preventing accidental name clashes and improving code safety.

Technical Response: Symbols allow us to create secured properties of an object so that no other part of code can accidentally accessed or overwritten. If a user object, for example, belongs to another codebase, and that code also works with the same user properties, we shouldn’t just add any fields to it, and that’s unsafe. If we use a Symbol(), the external library cannot accidentally access its property. In fact, the third-party library probably won’t even see it, so it’s probably all right to do. The benefit is a cloak created by Symbol to reduce object property conflicts.

Code Example:

// ...
let id = Symbol('id');

user[id] = 'Their id value';

Code Example: Conflicting Properties

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:
Interview Response: Yes, we can achieve this by wrapping the property in square brackets. This approach allows the property to be a key and not a string.

Code Example:

// 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:
Interview Response: To check if a property is a Symbol in a JavaScript object, you can use the typeof operator or the Symbol function.

Code Example:

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:
Interview Response: No, a Symbol will be skipped over in a for...in loop, as it is not considered an enumerable property.

Technical Response: No, you can access it directly, but for…in loop does not return the property. That is a part of the safeguarding of symbolic properties in principle. If another script or a library loops over our object, it will not unexpectedly access a symbolic property.

Code Example:

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:
Interview Response: Yes, you can use Object.getOwnPropertySymbols(obj) to copy all Symbol properties from an object obj to another object, along with Object.assign() to copy all non-Symbol properties.

Code Example:

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:
Interview Response: Yes, we can use the Symbol.for(key) to check the global registry and return it if available. Otherwise, it creates a new symbol Symbol(key) and stores it in the global registry by the given key. Symbols inside the registry are called global symbols.

Code Example:

// 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:
Interview Response: Symbol.for(key) creates a new symbol or returns an existing one from the global registry, while Symbol.keyFor(sym) returns the key for a symbol in the registry.

Code Example:

// 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:
Interview Response: No, Symbol.keyFor(sym) only works for symbols that were registered in the global symbol registry using Symbol.for(key). It will not work for non-global symbols or symbols created using the Symbol() constructor.


Code Example:

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:
Interview Response: Yes, you can use Symbols to create private properties in JavaScript classes by defining them as Symbol properties in the class constructor.

Technical Response: Yes, you can use the Symbol type to create private properties in classes in JavaScript. Symbol creates a unique identifier that can be used as an object property. This makes it hard to accidentally access or modify the property, giving a similar effect to a private property.

Code Example:

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.