es2piというライブラリーをこつこつと書き続け始めました。
What?
ES6のpolyfillと、それでも足りないと私が日頃感じていた機能を実装したJavaScript Libraryです。
2πという名前に、ES6に対する割り切れない想いを託しました。
Demo
とりあえずES5でPolyfillできるES6の機能までは実装ずみです。Polyfill以外でも関数よりもメソッドの方の方がふさわしいと思われる機能も一部実装してあります。その他の機能は徐々に追加して行く予定。
log('dan'.repeat(5) ); // in ES6 proposal log(['dan'].repeat(5) ); // NOT in ES6 log('-'.repeat(16)) // I love it! log(isNaN('dankogai') ); // log(Number.isNaN('dankogai')); // in ES6; log((0/0).isNaN()) // NOT in ES6; log((1/0).isNaN()) // ditto; log((1/0).isFinite()) // ditto; log(Number.toInteger(Math.PI)) // in ES6; log(Math.PI.toInteger()) // NOT in ES6; log('-'.repeat(16)) log(Object.isNil(null)); log(Object.isNil(undefined)); log(Object.isNil('')); log(Object.isNil(false)); log(Object.isNil(0)); log('-'.repeat(16)) log(''.isNil()); log(''.isPrimitive()); log(''.isString()); log('-'.repeat(16)) log([].isArray()); log({}.isObject()); log('-'.repeat(16)) var p = document.createElement('div'); log(p.typeOf()); log(p.classOf()); log('-'.repeat(16)) log(Object.keys(Object.prototype)); // thanks to ES5, this is blank! Object.getOwnPropertyNames(Object.prototype) .filter(function(k){ return ! k.match(/^__/) }) .forEach(function(k){ if (!Object[k].isFunction()) return; if ( Object[k].isBuiltIn() ) return; log('Object.prototype.' + k); });
Too Frequently Used Functions not to include
これらはライブラリー書く時にはほぼ必ず使うので、もう追加しちゃっていいでしょう。
var o = {name:"dankogai", lang:"perl"}; Object.extend(o, {lang:"javascript"}); log(o); Object.defaults(o, {lang:"PHP", ver:5}); log(o);
Deep Comparison and Cloning
js-object-cloneと同様です。
var src = { name: 'dankogai', lang: ['perl'] }; var dst = Object.clone(src); // shallow copy log( Object.is(src, dst)); // false log( Object.equals(src, dst) ); // true dst.lang.push('javascript'); log(src.lang ); // ["perl","javascript"] because dst is shallow-copied dst = Object.clone(src, true); // deep copy dst.lang = dst.lang.reverse(); log( src.lang ); // ["perl","javascript"] log( dst.lang ); // ["javascript","perl"] var src = new Date(0); var dst = Object.clone(src, true) log( src === dst ); log( Object.equals(src, dst) ); log( dst ); src = /./g; dst = Object.clone(src, true); log( src === dst ); log( Object.equals(src, dst) ); log( dst ); var Point = function(x, y) { if (!(this instanceof Point)) return new Point(x, y); this.x = x*1; this.y = y*1; }; Point.prototype = { distance: function(pt) { if (!pt) pt = Point(0,0); var dx = this.x - pt.x; var dy = this.y - pt.y; return Math.sqrt(dx*dx + dy*dy); } }; var src = Point(3,4); var dst = Object.clone(src, true); log( src === dst ); // false log( Object.equals(src,dst) ); // true log( dst.distance(Point(0,0)) ); // 5
Map and Set
Mapは文字列以外もキーになる「ハッシュ」。Perlの Tie::RefHash やRubyのHash
やPythonのdictionaryと同様です。
ECMAScript 6のリファレンス実装ではなんと配列を線形探索していて、Web上でも見つかるPolyfillのほとんどもこれに準ずるのですが、本実装ではキーがプリミティブの場合には配列の線形探索を避けるようにしてあります。
その部分だけ抜き出したものも
として用意してあります。
log('--Map --'.repeat(8)); var a = [], o = {}, m = Map(); [undefined, null, false, 0, a, o].forEach(function(v){ m.set(v, v); log(m.get(v)); }); log(m.get(undefined) === m.get('')) // false log(m.get(undefined) === m.get(undefined)) // true log(m.has([])); // false; log(m.has(a)); // true; a.push(false); log(m.get(a)); // [0] log(m.has({})); // false; log(m.has(o)); // true; o[undefined] = null; log(m.get(o)); // {undefined:null} log(m.items()); // JSON.strigify() converts undefined to null orz var s = Set(); log('--Set --'.repeat(8)); [undefined, null, false, 0, a, o].forEach(function(v){ s.add(v); log(s.has(v)); log(s.size); s.add(v); log(s.size); }); log(s.values());
Why?
結局 I can't get no satisfaction ちゅうことです。
- たとえばなんで
String.prototype.repeat
が入ったのにArray.prototype.repeat
がないの?いつまで私たちはArray.apply(null, Array(8))
ってドヤ顔したあげく、いたいけな初心者を置いてけぼりにすればよいのでしょう?こんなの[null].repeat(8)
でいいでしょうに。 - メソッドが生えない無毛で不毛な
null
とundefined
は仕方がないにしても、それ以外のオブジェクトはもっと自分のことをメソッドで語ってもいいでしょう。typeof o === 'number'
よりもo.isNumber()
の方がずっと楽ですし。(本当はgetterにして()も省きたかったけど、今は堪えてる) - せっかくES5が
Object.prototype
を人類に解放してくれたのに、これを使わぬ手はありません。 - おそらくES5に最も影響を与えたのはPrototype.jsですが、ES5の到着が遅すぎて、結局到着するころに繁栄したのはBuilt-in Prototypesを拡張しない代わりに一文字ネームスペースを事実上乗っ取ったjQueryやUnderscore.jsだったというのは悲しすぎる。
noConflict
なんてただの飾りです。えらい人にはそれがわからんのです。
本来の JavaScript の利用方法(Prototype 拡張)に立ち返り、Array.prototype, String.prototype, Number.prototype 等を拡張しています
ほんと、120%同意。Built-In Objects の Properties の descriptor が {enumerable: false, writable:true, configurable:ture}
となっていることに、もう一度思いを致すべきではないの?
というわけで、そのまま使っていただいても構わないのですし、そうしてもらいたいこともあって今回ははじめてminified versionも同封してあるのですが、むしろ「ぼくのかんがえるさいていげんぶんかてきなJavaScript」のたたき台として使ってもらうことを望んでいます。
Forks welcome! Pull requests welcome!!
Dan the JavaScripter Who Can't Get No Satisfaction
このブログにコメントするにはログインが必要です。
さんログアウト
この記事には許可ユーザしかコメントができません。