Douglas Crockford: "Advanced JavaScript"要点メモ
2010/09/05(日) 22:37 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年の内容なのですがはっきり言ってかなりレベル高い。
この時点でここまで掘り下げてる内容とは思ってなかった。

名前:  非公開コメント   

  • TB-URL  http://efcl.info/adiary/074/tb/