// basic Symbol example var BehindTheScene = (function(){ var symbol = new Symbol; function BehindTheScene(){ this[symbol] = {}; } BehindTheScene.prototype.get = function(k) { return this[symbol][k]; }; BehindTheScene.prototype.set = function(k, v) { return this[symbol][k] = v; }; return BehindTheScene; }()); var obj = new BehindTheScene; obj.set('key', 123); obj.key; // undefined obj.get('key'); // 123In few words symbol makes possible to attach properties directly without passing through a WeakMap. A similar behavior could be obtained indeed via WeakMaps:
// similar WeakMap example var BehindTheScene = (function(){ var wm = new WeakMap; function BehindTheScene(){ wm.set(this, {}); } BehindTheScene.prototype.get = function(k) { return wm.get(this)[k]; }; BehindTheScene.prototype.set = function(k, v) { return wm.get(this)[k] = v; }; return BehindTheScene; }()); var obj = new BehindTheScene; obj.set('key', 123); obj.key; // undefined obj.get('key'); // 123
Why Symbols
To be honest I am not sure but these somehow bring some magic to the object rather than wrapping magic around it, as it is for the WeakMap example, so at least performance should be better ... right? Well, the current shim VS shim says thatindexOf()
is faster than an implicit toString()
: check this test out by yourself ;)In any case it looks like private symbols will be a better way to go than WeakMap when all we would like to have is a private property. Symbols can be used as Enums too, being unique as any other object is.
Simulating Symbols In Current ES5 JavaScript
As easy as this:var Symbol; if (!Symbol) { Symbol = (function(Object){ // (C) WebReflection Mit Style License var ObjectPrototype = Object.prototype, defineProperty = Object.defineProperty, prefix = '__simbol' + Math.random() + '__', id = 0; function get(){/*avoid set w/out get prob*/} function Symbol() { var __symbol__ = prefix + id++; defineProperty( ObjectPrototype, this._ = __symbol__, { enumerable: false, configurable: false, get: get, // undefined set: function (value) { defineProperty(this, __symbol__, { enumerable: false, configurable: true, writable: true, value: value }); } } ); } defineProperty(Symbol.prototype, 'toString', { enumerable: false, configurable: false, writable: false, value: function toString() { return this._; } }); return Symbol; }(Object)); }A very basic example here:
var sym = new Symbol; var o = {}; o[sym]; // undefined o[sym] = 123; console.log(o[sym]); // 123 for (var k in o) { console.log(k); // nothing at all // there is nothing to for/in } delete o[sym]; // trueOf course, you can try also the very first example, the one with a shared, private, symbol variable, that will simply work as expected :)
Bear in mind, regardless being a hack, this script does not actually cause any problem to any other script or library you are using today but it needs ES5 compatible browsers such all mobiles plus all desktops and IE9 or greater.
I can't see why do I need Symbol?
ReplyDelete[js]
// basic Symbol example without a Symbol
var BehindTheScene = (function(){
var symbol = {};
function BehindTheScene(){
this[symbol] = {};
}
BehindTheScene.prototype.get = function(k) {
return this[symbol][k];
};
BehindTheScene.prototype.set = function(k, v) {
return this[symbol][k] = v;
};
return BehindTheScene;
}());
var bts = new BehindTheScene ;
bts.set('A',2);
bts.get("A");
/*
2
*/
[/js]
Perhaps my ES5 is a bit rusty ?
I didn't invent Symbols in ES6 so don't ask me but yeah, your example does not make sense becaus eyou cannot have 2 different symbols.
ReplyDeleteYou are simply using '[object Object]' as instance key plus that's enumerable and not private at all ... so yes, you did not get much about Symbols and the fact I've hacked ES5 to have them now
I saw @benvie's implementation a while back which was cool too, but yours is a lot more readable/compact. Kudos!
ReplyDelete... one can have "two different symbols" with the example I did ?
ReplyDeletenut I can have "two different symbols" with my example.
ReplyDeleteAlso here is a version (of course) which keeps symbol storage completely hidden:
ReplyDelete// basic Symbol example without a Symbol
var BehindTheScene = (function(){
var symbol = {};
function BehindTheScene(){
symbol = {};
}
BehindTheScene.prototype.get = function(k) {
return symbol[k];
};
BehindTheScene.prototype.set = function(k, v) {
return symbol[k] = v;
};
return BehindTheScene;
}());
var bts = new BehindTheScene ;
bts.set('A',2);
bts.set('B',3);
document.writeln(bts.get("A"));
document.writeln(bts.get("B"));
An working example without any Symbol lib
ReplyDelete@Andrea you are not sure why ES6 Symbol , but then you go on and 'hack it' in ES5. Please discuss ?
DBJDBJ I simply showed how Symbols are... and you don't need a closure to simulate them. You are stuck with a usage example, not with symbols and yes, your example won't work with more than a instance, mine will
ReplyDeleteAh sorry, I was "coding" on Galaxy S2, so please ignore (delete) my previous posts here ;o) Of course here is *extremely* simple code that does whatever you/me/we think are the requirements for ES6 Symbol.
ReplyDeleteI am addressing ES6 not you ... My example works and yours does too .. so what is the purpose of adding Symbols to ES6 ? Perhaps you can see it, but I can not ...