JavaScript学習ノート(38)複製属性継承

2567 ワード

コピー属性継承(Inherityance by Copying Propties)
もう一つの継承モードであるコピー属性継承を見てみましょう.このモードでは、オブジェクトが別のオブジェクトから機能を取得し、簡単にコピーします.
以下は関数exted()の簡単な実装の一例である.
function extend(parent, child) {

    var i;

    child = child || {};

    for (i in parent) {

        if (parent.hasOwnProperty(i)) {

            child[i] = parent[i];

        }

    }

    return child;

}
それは簡単に実現され、parentのメンバーを順次巡回してコピーします.この実装では、childはオプションです.既存のオブジェクトを転送して拡張しないと、新しいオブジェクトが作成されて戻ってきます.
var dad = {name: "Adam"};

var kid = extend(dad);

kid.name; // "Adam"

このような実現は、いわゆるオブジェクトの「レプリカ」である.深さコピーのもう一つの側面は、コピーする属性がオブジェクトまたは配列であるかどうかを確認することを意味します.浅いコピーを使って(JavaScriptでは参照によって対象が伝達されるので)、childの属性が変更され、たまたまこの属性がオブジェクトである場合、parentも修正されます.
このような場合は、実際には方法にとってより望ましい(関数も対象であり、参照によって伝達されるため)が、他のオブジェクトや配列に作用する場合は予期せぬ結果となるかもしれない.考えてみます
var dad = {

    counts: [1, 2, 3],

    reads: {

        paper: true

    }

};

var kid = extend(dad);

kid.counts.push(4);

dad.counts.toString(); // "1,2,3,4"

dad.reads === kid.reads; // true

exted()関数を修正して深さコピーを実現します.属性の種類がオブジェクトかどうかをチェックすることです.もしそうであれば、徐々に属性をコピーします.
もう一つの検査が必要です.対象は本物のオブジェクトかどうか、または行列ですか?前で論じた配列検査を使いましょう.
では、exted()の深さコピーバージョンは、このように見えるかもしれません.
function extendDeep(parent, child) {

    var i, toStr = Object.prototype.toString,

    astr = "[object Array]";

    child = child || {};

    for (i in parent) {

        if (parent.hasOwnProperty(i)) {

            if (typeof parent[i] === "object") {

                child[i] = (toStr.call(parent[i]) === astr) ? [] : {};

                extendDeep(parent[i], child[i]);

            } else {

                child[i] = parent[i];

            }

        }

    }

    return child;

}
新しいテストが実現しました.私たちに提供してくれた本物のオブジェクトのコピーは、childオブジェクトはそれらのparentsを修正しません.
var dad = {

    counts: [1, 2, 3],

    reads: {

        paper: true

    }

};

var kid = extendDeep(dad);

kid.counts.push(4);

kid.counts.toString(); // "1,2,3,4"

dad.counts.toString(); // "1,2,3"

dad.reads === kid.reads; // false

kid.reads.paper = false;

kid.reads.web = true;

dad.reads.paper; // true

このような属性コピーモードは簡単で広く使われています.例えば、Firebug(JavaScriptを使って書いたFirefox拡張)には、exted()という方法があります.浅いコピーとjQueryのexted()が深度コピーを実現しました.YUI 3は、Y.clone()という方法を提供し、1つの深さコピーを提供し、結合関数を介してchildオブジェクトコピー関数(次のコンテンツはより多くのバインディングがあります).
価値があるのは、このようなモードでは根本的にプロトタイプがなく、対象とその属性だけに関係があります.