Symbol でプライベートな値を作る
Experimental JavaScript Features の方に Symbol が使えると書かれていたので早速。
Symbol ってのはなんて言うか、固有のプロパティのキーになれるもの?っていう説明で良いのかな。
var s = new Symbol(); var obj = {}; obj[s] = "OK"; obj[s] // "OK";
obj[s]
の s は文字列化されずに、Symbolそのものとして動く。文字列キーとしては存在しないためs を使わずに得ることは不可能なのだ。
"use strict"; (function(global){ var className = new Symbol, name = new Symbol; var BaseProto = {}; BaseProto[className] = "Base"; Object.defineProperty(BaseProto, "className", { get: function () { return this[className]; }, }); function Person (aName) { this.name = aName; } Person.prototype = Object.create(BaseProto); Person.prototype[className] = "Person"; Object.defineProperty(Person.prototype, "name", { get: function () { return this[name]; }, set: function (val) { if (!val || typeof val !== "string") throw new TypeError("must be non-empty string"); return this[name] = val; }, }); global.Person = Person; }(this)); var p = new Person("t"); console.log(p.name); // "t" p.name = "teramako"; console.log(p.name); // "teramako" console.log(p.className); // "Person"
こんな感じで、(function(){ ... }())
の中でSymbol定義してやれば、他所からアクセスできないプロパティの出来上がりだ。
追記
と思ったけど、
var s = new Symbol; var o = {}; o[s] = "OK"; Object.keys(o); // => 0; Object.getOwnPropertyNames(o)[0] === s; // => true
Object.getOwnPropertyNames
からSymbolを取れてしまうことが判明。Object.keys
では取れないのに...。
仕様なのかバグなのか...バグだと思いたいけど、よく分からん...
追記(2013-04-12)
報告し忘れてた
See: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.2.3.4
Step 6.c.iv: makes sure key is String.
とバグ報告したものの、Revision: r14056で修正されていることが分かってクローズしてもらった。
ということで上記追記はそのうち修正されてCanaryに落ちてくると思われる。