ホームページ >ウェブフロントエンド >jsチュートリアル >jQuery_jquery の extend() メソッドと fn.extend() メソッドの詳細な説明

jQuery_jquery の extend() メソッドと fn.extend() メソッドの詳細な説明

WBOY
WBOYオリジナル
2016-05-16 15:56:481149ブラウズ

これら 2 つのメソッドは同じコードを使用します。1 つは jQuery オブジェクトまたは通常のオブジェクトのプロパティとメソッドを結合するために使用されます。次に、基本的な使用例をいくつか示します。

HTML コードは次のとおりです:

コードをコピーします コードは次のとおりです:


<頭>

                                                                                                                                                                                                                                                                                                          






以下の js で使用法を記述します:

2 つの通常のオブジェクトをマージします

コードをコピーします コードは次のとおりです:
// 2 つの通常のオブジェクトの属性をマージします
var obj1={名前:'トム',年齢:22};
var obj2={名前:'ジャック',高さ:180};
console.log($.extend(obj1,obj2)); //オブジェクト {名前: "ジャック"、年齢: 22、身長: 180}


jQuery オブジェクトにプロパティまたはメソッドを追加します

コードをコピーします コードは次のとおりです:
$.extend({hehe:function(){alert('hehe');}});
$.hehe(); //アラート('hehe')


この使い方は非常に重要で、jQuery内にインスタンスのプロパティやメソッドを追加する実装方法でもあり、jQueryのプラグインを記述する方法でもあります。 jQuery 1.7.1 のメソッドを使用して独自のメソッドとプロパティを拡張

コードをコピーします コードは次のとおりです:
jQuery.extend({
noConflict: function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}
If ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
return jQuery;
}、
// DOM は使用する準備ができていますか? 発生したら true に設定します。
isReady: false、
// 事前に待機するアイテムの数を追跡するカウンター
//ready イベントが発生します。 #6781
を参照してください。 準備完了: 1、
......


この例では、オブジェクト パラメーターが 1 つだけ渡されるため、デフォルトでは、これがマージおよび変更されるオブジェクトとみなされます

jQuery オブジェクト インスタンスにプロパティまたはメソッドを追加する

コードをコピーします コードは次のとおりです:
//jQuery インスタンスの拡張マージ
console.log($('img').extend({'title':'img'}));//[img, img#img.img, prevObject: jQuery.fn.jQuery.init[1], context : ドキュメント、セレクター: "img"、タイトル: "img"、コンストラクター: 関数…]


マージのみを行い、マージされるオブジェクトは変更しないでください

コードをコピーします コードは次のとおりです:
var obj1={名前:'トム',年齢:22};
var obj2={名前:'ジャック',高さ:180};
console.log($.extend(obj1,obj2)); //オブジェクト {名前: "ジャック"、年齢: 22、身長: 180}
console.log(obj1); //オブジェクト {名前: "ジャック"、年齢: 22、身長: 180}

デフォルトでは、マージされるオブジェクトは返された結果のように変更されます。マージされたオブジェクトを取得したいだけで、元のオブジェクトを破棄したくない場合は、このメソッドを使用できます。

コードをコピーします コードは次のとおりです:

var obj1={名前:'トム',年齢:22};
var obj2={名前:'ジャック',高さ:180};
var empty={};
console.log($.extend(empty,obj1,obj2)); //オブジェクト {名前: "ジャック"、年齢: 22、身長: 180}
console.log(obj1); //オブジェクト {名前: "トム"、年齢: 22}

使用する場合は、再帰的マージまたはディープ コピー

コードをコピーします コードは次のとおりです:

var obj1={名前:'トム',愛:{飲む:'牛乳',食べる:'パン'}};
var obj2={名前:'ジャック',愛:{飲み物:'水',スポーツ:'フットボール'}};
console.log(($.extend(false,obj1,obj2)).love); //オブジェクト {ドリンク: "水"、スポーツ: "サッカー"}
console.log(($.extend(true,obj1,obj2)).love); //オブジェクト {飲む: "水"、食べる: "パン"、スポーツ: "サッカー"}

詳しい使い方はリファレンスマニュアルをご覧くださいhttp://www.w3cschool.cc/manual/jquery/

1.7.1 ソース コードでどのように実装されているかを分析してみましょう:

コードをコピーします コードは次のとおりです:

jQuery.extend = jQuery.fn.extend = function() {
var オプション、名前、ソース、コピー、copyIsArray、クローン、
ターゲット = 引数[0] {},
i = 1,
長さ = 引数.長さ,
深い = false;
...
}

まず、変数のセットが定義されます。パラメータの数が不定であるため、引数オブジェクトを直接呼び出して、渡されたパラメータにアクセスします。

変数オプション: ソース オブジェクトを指します。
変数名: ソース オブジェクトの属性名を表します。
変数 src: ターゲット オブジェクトの属性の元の値を表します。
変数コピー: ソース オブジェクトの属性の値を表します。
変数 copyIsArray: 変数 copy が配列であるかどうかを示します。
変数clone:ディープコピー時のオリジナル値の補正値を表します。
変数 target: ターゲット オブジェクトを指します。
変数 i: ソース オブジェクトの開始インデックスを表します。
可変長: パラメータの数を示し、変数ターゲットを変更するために使用されます。
変数 deep: ディープ コピーを実行するかどうかを示します。デフォルトは false です。

コードの実装をよりよく理解するために、ソース コードの実行を観察するためのデモンストレーションとして上記の例を示します

コードをコピーします コードは次のとおりです:

var obj1={名前:'トム',愛:{飲む:'牛乳',食べる:'パン'}};
var obj2={名前:'ジャック',愛:{飲み物:'水',スポーツ:'フットボール'}};
$.extend(true,obj1,obj2)

ソースコード解析

コードをコピーします コードは次のとおりです:

// ディープコピー状況を処理します
If ( typeof target === "boolean" ) {
深い = ターゲット;
ターゲット = 引数[1] {};
// ブール値とターゲットをスキップします
i = 2;
}

最初のパラメータがブール値の場合は、最初のパラメータの値をディープに与え、2 番目のパラメータが存在しない場合は、ターゲット オブジェクトとして使用します。この例では、最初のパラメータが true で、次に deep が true に変更されるため、これが行われます。ソース オブジェクトの開始添字は 2 です。つまり、ソース オブジェクトとして 3 番目の添字から開始することを意味します (この例では obj2

)。

コードをコピーします コードは次のとおりです:

// ターゲットが文字列または何かである場合の処理​​ (ディープコピーで可能)
If ( typeof target !== "object" && !jQuery.isFunction(target) ) {
ターゲット = {};
}

ターゲットはここでさらに処理されます。たとえば、文字列は独自のメソッドと属性を呼び出すことができます。カスタム属性の追加は無効です。

コードをコピーします コードは次のとおりです:
// 引数が 1 つだけ渡された場合、jQuery 自体を拡張します
If ( length === i ) {
ターゲット = this;
—私;
}

length 属性が i の値と等しい場合は、ターゲット オブジェクトが存在しないことを意味します。通常、長さは i の値より大きいはずです。このとき、これをターゲット オブジェクトとして使用し、縮小します。 i の値よりも大きい長さの値を得るには、i の値を 1 増やします (i より 1 大きい)

これは、ターゲット オブジェクトが

に渡されない限り、属性をそれ自体に拡張する jQuery のメソッドの実装原則です。

考えられる 2 つの状況: $.extend(obj) または $.extend(false/true,obj);

コードをコピー コードは次のとおりです:

    for ( ; i         // 非 null/未定義値のみを処理します
        if ( (オプション = 引数[ i ]) != null ) {
            // 基本オブジェクトを拡張します
            for (オプションの名前) {
                src = ターゲット[名前];
                copy = オプション[名前];
                // 終わりのないループを防止します
                if (ターゲット === コピー) {
                    続行;
                }
                // プレーンなオブジェクトまたは配列をマージする場合は再帰します
                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    if ( copyIsArray ) {
                        copyIsArray = false;
                        クローン = src && jQuery.isArray(src) ?ソース: [];
                    } else {
                        clone = src && jQuery.isPlainObject(src) ?ソース: {};
                    }
                    // 元のオブジェクトは決して移動せず、クローンを作成してください
                    target[ name ] = jQuery.extend( deep, clone, copy );
                // 未定義の値を持ち込まないでください
                } else if (コピー !== 未定義) {
                    ターゲット[名前] = コピー;
                }
            }
        }
    }

この部分はこのメソッドの核心であり、arguments オブジェクトの最初の下の値から循環操作が最初に開始され、ソース オブジェクトが null または未定義の場合はその

を確認できます。

ソースオブジェクトは不定真のものであり、他の種類の文字列比のようなものでもよい:

复制代 代码如下:

console.log($.extend({'name':'tom'},'aa'));   //オブジェクト {0: "a"、1: "a"、名前: "tom"}

是不是感觉很奇怪啊?究竟是怎么实现的呢?下面接着看

フィルタが完了した後、循環 src の実行が開始されます。保存されているのはアイテム オブジェクトの特定のボタンの値であり、コピー プロパティが保存されているソース オブジェクトの特定のボタンの値であり、この 2 つのボタンはすべて同じです。

复制代码代码如下:

// 終わりのないループを防止します
If (ターゲット === コピー) {
続行;
}

ソース オブジェクトの特定の属性値がターゲット オブジェクトである場合、無限ループが発生してプログラムがクラッシュする可能性があるため、ここではこのループをスキップできるように制限が設けられています。例:

コードをコピーします コードは次のとおりです:

var o = {};
o.n1 = o;
$.extend( true, o, { n2: o } );
// 例外をスローします:
// キャッチされない RangeError: 最大呼び出しスタック サイズを超えました

しかし、そうすることで、次のような通常の状況にも不当な影響を与えることになります。

コードをコピーします コードは次のとおりです:

var obj1={a:'a'}
var obj2={a:obj1};
console.log($.extend(obj1,obj2)); //オブジェクト {a: "a"}

この状況では、ソース オブジェクトの値がターゲット オブジェクトと等しいという条件も満たされますが、以下ではソース内のこの段落をコメントアウトしているため、obj1 の a の属性値は変更されていないことがわかります。

を実行する前のコード

コードをコピーします コードは次のとおりです:

オブジェクト {a: オブジェクト}

現時点では、この部分は改善が必要だと個人的には感じています。

次に、ディープコピーかどうかを判断する if 判定があります。まず、ディープコピーは見ずに、一般的な

を確認します。

コードをコピーします コードは次のとおりです:
ターゲット[名前] = コピー;

これは非常に簡単です。コピーに値があれば、それがターゲット オブジェクトに直接コピーされ、ターゲット オブジェクトに変更が加えられると、マージが完了します。

for ループの後、新しいターゲット オブジェクトが返されるため、ターゲット オブジェクトは最終的に変更され、結果は返された結果と同じになります。

コードをコピーします コードは次のとおりです:
// 変更されたオブジェクトを返します
ターゲットを返す;
};

ディープコピーの処理方法について話しましょう

まず、deep が true であり、copy が値を持ち、オブジェクトまたは配列であることを確認してから (オブジェクトまたは配列でない場合、ディープ コピーは問題外です)、それから配列とオブジェクトによって処理されることを見てみましょう。最初の配列:

コードをコピーします コードは次のとおりです:
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) : [];
} else {

clone = src && jQuery.isPlainObject(src) : {};
}

配列 copyIsArray の値が true の場合は、内部に移動して値を false に変更します。現在のループのソース オブジェクト属性について、ターゲット オブジェクトに属性があるかどうかを判断します。配列である場合、それは元の配列です。配列が変更されていない場合は、ソース オブジェクトの現在の属性が配列であるため、最後のターゲット要素も配列でなければなりません。配列またはオブジェクトのいずれか。ターゲット オブジェクトの現在のプロパティをオブジェクトに変更します。

コードをコピーします コードは次のとおりです:
// 元のオブジェクトは決して移動せず、クローンを作成してください
Target[ name ] = jQuery.extend( deep, clone, copy );

次に、ソース オブジェクト (配列またはオブジェクト) の現在の属性値と変更されたターゲット オブジェクトの現在の属性を再帰的にマージし、返された新しい配列またはオブジェクトをターゲット オブジェクトに割り当て、最終的にディープ コピーを実現します。

しかし、ここには次のようなかなり奇妙な現象があります:

コードをコピーします コードは次のとおりです:

console.log($.extend({a:1},'aa')); //オブジェクト {0: "a", 1: "a", a: 1}

元のソース オブジェクトは必ずしもオブジェクト e である必要はなく、文字列を分割してターゲット オブジェクトと結合することができます。for...in ループは文字列に対して動作することがわかります。

コードをコピーします コードは次のとおりです:

var str='aa';
for(str の変数名){
console.log(名前);
console.log(str[名前])
}

これも可能です。文字列を分割し、数値の下付き文字に従って読み取りますが、ソース コードでは

コードをコピーします コードは次のとおりです:

if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) )

は配列とオブジェクトに限定されているため、ディープコピー中には効果がありませんか?

テストの結果、ソースコード内のコピーされた値は匿名関数に変わったため、ディープコピーも可能です

alert(jQuery.isPlainObject(copy)); //true

なぜこれが関数なのかについては、まだ理解できていないので、後で解決することにします。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。