综合开发

Is Symbol really useful?

微信扫一扫,分享到朋友圈

Is Symbol really useful?

Is Symbol really useful in JavaScript?

Symbols, the underestimated feature introduced in ES2015. Does it have any other purpose than interview questions?

Quick recap, what are those “Symbols” anyway?

primitive value that represents a unique, non-String Object property key

That’s Symbol definition from the current spec . But what does it mean? You probably know other primitive types in JS ( Undefined , Null , Boolean , Number , BigInt or String ). Symbol is another one. I know that is not much and it sounds like defining recursion:

To understand recursion, you must first understand recursion

In programming languages, all primitive types are a just bunch of bytes stored in memory. It doesn’t matter if it’s a string or number, from a data perspective it’s still just bytes. In the case of symbols, they are tokens that serves as unique IDs.

How to use Symbol

// string "id" is a Symbol's description
const id = Symbol('id');
// you can also create Symbol without description
const noDescriptionId = Symbol();

We’ve just created id which is a Symbol. But the important thing is that id !== Symbol('id') . Like I’ve said earlier Symbols are unique.

Unless they aren’t…

There is another way to create Symbol, and it’s called

Symbol.for('id');
assert(Symbol.for('id') === Symbol.for('id')); // true

OK, what happened here? We’ve just used global Symbol registry to store our Symbol. As the name says it’s a global registry and global in this case is also cross-realm (in JS that mean Symbol created inside an iframe and is the same as in your current execution context).

Aside note: You can check if Symbol is unique or not. For that, you can use Symbol.keyFor(yourSymbol) . If yourSymbol is global, then it returns the Symbol’s description ( id ) as a string, else it returns undefined .

assert(Symbol.keyFor(Symbol.for('id')) === 'id');
assert(Symbol.keyFor(Symbol('id')) === undefined);

Properties you need to know

  • Symbol will never conflict with Object key. You can use Symbol as the object key store[Symbol.for('id')] = 42 .
  • Keys created using Symbol is not iterable. So when you call Object.values(store) you won’t get 42 unless there is another key (not Symbol key) with that value. That’s a really useful property because it won’t change library behavior when you add another property.
  • To extract Symbols from the object, you can use Object.getOwnPropertySymbols() .
  • Symbols are copied to other objects. Every enumerable Symbol is copied from obj a into obj b when Object.assign(a, b) is called.

Symbol’s usefulness

Now when you know what a Symbol is, we can discuss why should you consider Symbols useful? Let’s suppose you’re creating a library and want to give your user a possibility to extend your library.

Your library is called stateOfTheArtValidation ( stav to make it short). And it exports the list of available extensions you can assign to your object.

export const extensibleSymbols = {
VALIDATION: Symbol('validationFun'),
REQUIRED: Symbol('required'),
};

Now we can use any of those Symbols in our objects.

const myObj = {
someProp: 'anyValue',
[stav.Symbols.VALIDATION]: element => element.hasOwnProperty('someProp'),
};

Let me first show you what your library does with that before we discuss it.

// somewhere in our library
validate: (...objectsToValidate) => {
const validations = [];
for (const objToValidate of objectsToValidate) {
if (typeof objToValidate[this.Symbols.VALIDATION] === 'function') {
validations.push({
result: objToValidate[this.Symbols.VALIDATION](objToValidate),
});
} else {
validations.push({
result: this.standardValidation(objToValidate),
});
}
}
return validations;
};

validate is a method from your library. But there are some cases when you want to give users the option to apply their validation instead of your standardValidation method. Instead of defining a list of string properties which user can use to attach their validation method, you’ve defined Symbol for it. That way there is a 0% chance to have a conflict with any of the existing keys on that object, so a user cannot accidentally overwrite the property you want to use.

Ofc that example is not really useful IRL but you get an idea.

Well-Known Symbols

Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification.

Someone already thought about that by creating built-in Symbols in JS. Those Symbols are useful to overwrite/add functionalities of/to objects. For instance, you can use Symbol.iterator to define iterator and enable your object to be iterable in the way you want.

const myObj = {
test: 'test',
};
myObj[Symbol.iterator] = function* myGenerator() {
yield this.test;
yield 'See ya!';
};
for (const val of myObj) {
console.log(val);
}

Prints:

test
See ya!

Conclusion

Now you understand how powerful and useful Symbols might be. Probably you’re going to use built-in Symbols more often than defining your own. But library creators (like you :P ) have another way for users to extend library functionality.

微信扫一扫,分享到朋友圈

Is Symbol really useful?

Python: flattening a JSON

上一篇

Django News - Issue 10 - Feb 14th 2020

下一篇

你也可能喜欢

评论已经被关闭。

插入图片

热门栏目

Is Symbol really useful?

长按储存图像,分享给朋友