Douglas Crockford: "Advanced JavaScript"要点メモ
■スライドP28
Prototype Inheritanceの図は分かりやすい。■Singleton P46
グローバルなものはできるだけ使わない。いわゆるクロージャー的なものでprivateなプロパティやメソッドを扱える。
var singleton = function () {
var privateVariable;
function privateFunction(x) {
...privateVariable...
}
return {
firstMethod: function (a, b) {
...privateVariable...
},
secondMethod: function (c) {
...privateFunction()...
}
};
}();
■Power Constructor P48
Power Constructorはベースとなるものをprototype先にしたthatに、内部でprivateなメソッドやプロパティをもてる。その拡張したthatをreturnする。that経由でprivateなものにアクセスはできるけど直接privateには触れないSingletonの特性を持ってる。
thisだけじゃなくてthatもシンタックスハイライトしておいていい気がする。
// obect.create - oをプロトタイプとして新しいオブジェクトを返す
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
// Power Constructor
function powerConstructor() {
var that = object(my_base),
privateVariable;
function privateFunction(x) {}
that.firstMethod = function (a, b) {
...privateVariable...
};
that.secondMethod = function (c) {
...privateFunction()...
};
return that;
}
■Pseudoclassical InheritanceとParasitic Inheritance
Pseudoclassical Inheritanceはよく本などで見るようなprototype継承。無駄に複雑でわかりにくい。
function Gizmo(id) {
this.id = id;
}
Gizmo.prototype.toString = function () {
return "gizmo " + this.id;
};
function Hoozit(id) {
this.id = id;
}
Hoozit.prototype = new Gizmo();
Hoozit.prototype.test = function (id) {
return this.id === id;
};
Parasitic Inheritanceはprototypeに頼らないで浸食する感じで継承させる。見た目がかなりシンプルにできる。
function gizmo(id) {
return {
id: id,
toString: function () {
return "gizmo " + this.id;
}
};
}
function hoozit(id) {
var that = gizmo(id);
that.test = function (testid) {
return testid === this.id;
};
return that;
}
// e.g
var foo = hoozit("hoge");
foo.test("hoge");// true
foo.id;// "hoge" => idに直接アクセスできる
Secrets - Parasitic Inheritanceからさらにidをprivateなものにする場合。foo.idで参照できなくさせるには。
function gizmo(id) {
return {
toString: function () {
return "gizmo " + id;
}
};
}
function hoozit(id) {
var that = gizmo(id);
that.test = function (testid) {
return testid === id;
};
return that;
}
var foo = hoozit("hoge");
foo.test("hoge");// true
foo.id;// undefined => idはprivateに
これだとhoozitとgizmoの間でプロパティのやり取りがしにくいので、hoozitとgizmo間では共有するけど、外からはprivateなものを作るShared Secretsの話が出てくる(いいとこ取り)
function gizmo(id, secret) {
secret = secret || {};
secret.id = id;
return {
toString: function () {
return "gizmo " + secret.id;
};
};
}
function hoozit(id) {
var secret = {}, /*final*/
that = gizmo(id, secret);
// Secretsの場合とは違い、ここでsecret.idが扱える。
that.test = function (testid) {
return testid === secret.id;
};
return that;
}
Parasitic Inheritance以下はprototypeを使ってないので親のメソッドを呼ぶSuper Methodsが定義できていない。Super Methodsを定義するには以下のようにfunc.applyを使う。
function hoozit(id) {
var secret = {},
that = gizmo(id, secret),
super_toString = that.toString;// superのメソッドを取る
that.test = function (testid) {
return testid === secret.id;
};
that.toString = function () {
return super_toString.apply(that, []);// thisのスコープをthat(super)にしてSuper Methodを実行
};
return that;
}
■later method - P61
一定時間後に実行するメソッド定義これ短いけどものすごくエッセンスが詰まってる内容。(2006年にこれとか凄い)
Object.prototype.later = function(msec, method) {
var that = this,
args = Array.prototype.slice.apply(arguments, [2]);// argumentsを配列扱い
if (typeof method === 'string') {
method = that[method];// 実行するメソッド
}
setTimeout(function() {
method.apply(that, args);// スコープをちゃんとしてmethodを実行
}, msec);
return that;
};
■Multiples - P64
こんな風に書くと問題が起きる。ループが回りきった後のiで統一されてしまうので全部同じ結果
for (i ...) {
var div_id = divs[i].id;
divs[i].onmouseover = function () {
show_element_id(div_id);
};
}
なのでループ内でスコープを作って行う。
for (i ...) {
var div_id = divs[i].id;
divs[i].onmouseover = function (id) {
return function () {
show_element_id(id);
};
}(div_id);
}
// forループとスコープの関係作りでよく使う。letが使えないときとかは特に
for(...)(function(elm){
// 処理
})(ary[i]);
2006年の内容なのですがはっきり言ってかなりレベル高い。この時点でここまで掘り下げてる内容とは思ってなかった。
コメント(0件)
- TB-URL http://efcl.info/adiary/074/tb/