Maison >interface Web >js tutoriel >Explication détaillée des méthodes extend() et fn.extend() dans jQuery_jquery

Explication détaillée des méthodes extend() et fn.extend() dans jQuery_jquery

WBOY
WBOYoriginal
2016-05-16 15:56:481149parcourir

Ces deux méthodes utilisent le même code. L'une est utilisée pour fusionner des propriétés et des méthodes pour des objets jQuery ou des objets ordinaires. Voici quelques exemples d'utilisation de base :

Le code html est le suivant :

Copier le code Le code est le suivant :





                                                                                                                                                                                                                                                                                                          






Écrivez l'utilisation en js ci-dessous :

Fusionner deux objets ordinaires

Copier le code Le code est le suivant :
//Fusion des attributs de deux objets ordinaires
var obj1={nom :'Tom',âge:22};
var obj2={nom : 'Jack', hauteur : 180};
console.log($.extend(obj1,obj2)); //Objet {nom : "Jack", âge : 22, taille : 180}

Ajouter des propriétés ou des méthodes aux objets jQuery

Copier le code Le code est le suivant :
$.extend({hehe:function(){alert('hehe');}});
$.hehe(); //alerte('hehe')

Cette utilisation est très importante. C'est la méthode d'implémentation pour ajouter des propriétés et des méthodes d'instance ainsi que des propriétés et des méthodes de prototype dans jQuery. C'est également la méthode d'écriture de plug-ins jQuery. Voici l'utilisation de l'extension. méthode dans jQuery 1.7.1 pour étendre ses propres méthodes et propriétés

Copier le code Le code est le suivant :
jQuery.extend({
noConflict : fonction (profond) {
            if ( window.$ === jQuery ) {
               fenêtre.$ = _$;
>
Si ( deep && window.jQuery === jQuery ) {
               window.jQuery = _jQuery;
>
         renvoyer jQuery ;
},
// Le DOM est-il prêt à être utilisé ? Défini sur true une fois que cela se produit.
isReady : faux,
// Un compteur pour suivre combien d'articles attendre avant
// l'événement ready se déclenche. Voir #6781
prêtAttendez : 1,
.....

Dans cet exemple, un seul paramètre d'objet est transmis, donc par défaut, il est considéré comme l'objet à fusionner et à modifier

Ajouter des propriétés ou des méthodes aux instances d'objets jQuery

Copier le code Le code est le suivant :
//Fusion étendue pour les instances jQuery
console.log($('img').extend({'title':'img'}));//[img, img#img.img, prevObject : jQuery.fn.jQuery.init[1], contexte : document, sélecteur : "img", titre : "img", constructeur : fonction…]

Fusionnez uniquement et ne modifiez pas les objets à fusionner

Copier le code Le code est le suivant :
var obj1={nom :'Tom',âge:22};
var obj2={nom : 'Jack', hauteur : 180};
console.log($.extend(obj1,obj2)); //Objet {nom : "Jack", âge : 22, taille : 180}
console.log(obj1); //Objet {nom : "Jack", âge : 22, taille : 180}

Par défaut, l'objet à fusionner est modifié comme le résultat renvoyé. Si vous souhaitez simplement obtenir un objet fusionné mais ne souhaitez détruire aucun des objets d'origine, vous pouvez utiliser cette méthode

Copier le code Le code est le suivant :

var obj1={nom :'Tom',âge:22};
var obj2={nom : 'Jack', hauteur : 180};
var vide={};
console.log($.extend(empty,obj1,obj2)); //Objet {nom : "Jack", âge : 22, taille : 180}
console.log(obj1); //Objet {nom : "Tom", âge : 22}

Si utilisé, fusion récursive ou copie profonde

Copier le code Le code est le suivant :

var obj1={name : 'Tom',love :{drink:'milk',manger :'bread'}};
var obj2={name :'Jack',love:{drink:'water',sport:'football'}};
console.log(($.extend(false,obj1,obj2)).love); //Objet {boisson : "eau", sport : "football"}
console.log(($.extend(true,obj1,obj2)).love); //Objet {boisson : "eau", manger : "pain", sport : "football"}

Pour une utilisation détaillée, veuillez consulter le manuel de référence http://www.w3cschool.cc/manual/jquery/

Analysons comment il est implémenté dans le code source de la 1.7.1 :

Copier le code Le code est le suivant :

jQuery.extend = jQuery.fn.extend = function() {
options var, nom, src, copie, copyIsArray, clone,
cible = arguments[0] || {},
je = 1,
longueur = arguments.longueur,
profond = faux ;
...
>

Tout d'abord, un ensemble de variables est défini. Le nombre de paramètres étant incertain, l'objet arguments est directement appelé pour accéder aux paramètres passés

Options variables : pointe vers un objet source.
Nom de variable : représente un nom d'attribut d'un objet source.
Variable src : Représente la valeur originale d'un attribut de l'objet cible.
Copie variable : représente la valeur d'un attribut d'un objet source.
Variable copyIsArray : indique si la variable copy est un tableau.
Clone variable : représente la valeur de correction de la valeur originale lors de la copie profonde.
Cible variable : pointe vers l'objet cible.
Variable i : représente l'index de départ de l'objet source.
Longueur variable : indique le nombre de paramètres et permet de modifier la cible variable.
Variable deep : indique s'il faut effectuer une copie approfondie, la valeur par défaut est false.

Afin de mieux comprendre l'implémentation du code, voici un exemple donné ci-dessus à titre de démonstration pour observer l'exécution du code source

Copier le code Le code est le suivant :

var obj1={name : 'Tom',love :{drink:'milk',manger :'bread'}};
var obj2={name :'Jack',love:{drink:'water',sport:'football'}};
$.extend(true,obj1,obj2)

Analyse du code source

Copier le code Le code est le suivant :

// Gérer une situation de copie profonde
Si ( typeof target === "boolean" ) {
profond = cible ;
cible = arguments[1] || {};
// saute le booléen et la cible
je = 2;
>

Déterminez s'il s'agit d'une copie profonde. Si le premier paramètre est une valeur booléenne, donnez la valeur du premier paramètre à deep, puis utilisez le deuxième paramètre comme objet cible. attribuez-le à un objet vide, remplacez l'indice de l'objet source par 2. Dans cet exemple, cela est fait ici car le premier paramètre est vrai, puis deep est modifié en vrai. La cible est modifiée par le deuxième paramètre. est obj1. L'indice de départ de l'objet source est 2, ce qui signifie commencer à partir du troisième comme objet source, qui est obj2

dans cet exemple.

Copier le code Le code est le suivant :

// Gérer le cas où la cible est une chaîne ou quelque chose (possible en copie complète)
Si ( typeof target !== "object" && !jQuery.isFunction(target) ) {
Cible = {};
>

La cible est traitée davantage ici. L'ajout d'attributs personnalisés n'est pas valide pour les types de données non-objet et fonction. Par exemple, les chaînes peuvent appeler leurs propres méthodes et attributs

.

Copier le code Le code est le suivant :

// étend jQuery lui-même si un seul argument est passé
Si ( longueur === i ) {
cible = ceci ;
​​​​—je;
>

Si l'attribut length est égal à la valeur de i, cela signifie qu'il n'y a pas d'objet cible. Dans des circonstances normales, la longueur devrait être supérieure à la valeur de i. Ensuite, utilisez-le comme objet cible à ce moment et réduisez-le. la valeur i par un pour obtenir la valeur de longueur supérieure à la valeur i (1 supérieure à i)

C'est le principe d'implémentation de la méthode jQuery d'extension des attributs à lui-même, tant que l'objet cible n'est pas transmis dans

Deux situations possibles : $.extend(obj) ou $.extend(false/true,obj);

Copier le code Le code est le suivant :

    pour ( ; je < longueur; je ) {
        // Ne traite que les valeurs non nulles/non définies
        if ( (options = arguments[ i ]) != null ) {
            // Étendre l'objet de base
            pour (nom dans les options) {
                src = cible[nom];
                copie = options[ nom ];
                // Empêcher une boucle sans fin
                if ( target === copy ) {
                    continuer ;
                >
                // Récursif si nous fusionnons des objets ou des tableaux simples
                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    si ( copyIsArray ) {
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];
                    } autre {
                        clone = src && jQuery.isPlainObject(src) ? src : {};
                    >
                    // Ne déplacez jamais les objets originaux, clonez-les
                    target[ nom ] = jQuery.extend( deep, clone, copy );
                // N'apportez pas de valeurs non définies
                } else if ( copie !== non défini ) {
                    cible[nom] = copie;
                >
            >
        >
    >

这个部分就是此方法的核心了,从arguments对象的第i个下标值开始循环操作首先过滤掉源对象是nu ll或者是undefined的情况可以看到其实

源对象不一定真的就是对像,也可以是其他类型的值比如字符串比如这样写:

复制代码 代码如下 :

console.log($.extend({'name':'tom'},'aa'));   //Objet {0 : "a", 1 : "a", nom : "tom"}

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

的值,这两个键都是一样的

复制代码 代码如下 :

// Empêcher une boucle sans fin
Si (cible === copie) {
                         continuer ;
                }

Si une certaine valeur d'attribut de l'objet source est l'objet cible, cela peut provoquer une boucle infinie et provoquer le crash du programme, donc une restriction est faite ici pour lui permettre de sauter cette boucle. Par exemple :

.

Copier le code Le code est le suivant :

var o = {};
o.n1 = o;
$.extend( true, o, { n2: o } );
// lève une exception :
// Uncaught RangeError : taille maximale de la pile d'appels dépassée

Mais cela affectera également injustement certaines situations normales telles que :

Copier le code Le code est le suivant :

var obj1={a:'a'}
var obj2={a:obj1};
console.log($.extend(obj1,obj2)); //Objet {a: "a">

Cette situation satisfait également que la valeur de l'objet source est égale à l'objet cible, mais il s'avère que la valeur de l'attribut a de obj1 n'a pas été modifiée, car continue est exécuté Ci-dessous, commentez ce paragraphe dans la source. code avant d'exécuter

Copier le code Le code est le suivant :

Objet {a : Objet>

Pour le moment, il a été modifié normalement. Je pense personnellement que ce domaine a besoin d'être amélioré

Ensuite, il y a un jugement if, qui consiste à distinguer s'il s'agit d'une copie profonde. Tout d'abord, ne regardez pas la copie profonde et regardez d'abord le général

.

Copier le code Le code est le suivant :

cible[nom] = copie;

C'est très simple. Tant que la copie a une valeur, elle est copiée directement sur l'objet cible. Si l'objet cible a quelques modifications, il est ajouté de cette manière.

Après la boucle for, le nouvel objet cible est renvoyé, donc l'objet cible est finalement modifié et le résultat est le même que le résultat renvoyé.

Copier le code Le code est le suivant :

// Renvoie l'objet modifié
Cible de retour ;
};

Parlons de la façon de gérer la copie approfondie

Assurez-vous d'abord que deep est vrai, que la copie a une valeur et est un objet ou un tableau (s'il ne s'agit pas d'un objet ou d'un tableau, la copie profonde est hors de question), puis elle est traitée par des tableaux et des objets. au tableau en premier :

Copier le code Le code est le suivant :

si ( copyIsArray ) {
          copyIsArray = false;
​ ​ ​ clone = src && jQuery.isArray(src) ? src : [];

} autre {
​​​​clone = src && jQuery.isPlainObject(src) ? >

Si la valeur du tableau copyIsArray est vraie, allez à l'intérieur et changez la valeur en false Pour l'attribut d'objet source de la boucle actuelle, l'objet cible peut l'avoir ou non. Si c'est le cas, jugez si c'est le cas. est un tableau. Si c'est le cas, c'est l'original. Si le tableau est inchangé, laissez-le devenir un tableau, car puisque l'attribut actuel de l'objet source est le tableau, le dernier élément cible doit également être un tableau. Soit un tableau, soit un objet. Modifiez les propriétés actuelles de l'objet cible en un objet.

Copier le code Le code est le suivant :
// Ne déplacez jamais les objets originaux, clonez-les
Target[ nom ] = jQuery.extend( deep, clone, copy );

Fusionnez ensuite de manière récursive la valeur d'attribut actuelle de l'objet source (qui est un tableau ou un objet) et l'attribut actuel de l'objet cible modifié et attribuez le nouveau tableau ou objet renvoyé à l'objet cible, pour finalement obtenir une copie approfondie.

Mais il y a ici un phénomène assez étrange, comme celui-ci :

Copier le code Le code est le suivant :

console.log($.extend({a:1},'aa')); //Objet {0 : "a", 1 : "a", a : 1}

L'objet source d'origine n'est pas nécessairement l'objet e, et la chaîne peut être divisée et fusionnée avec l'objet cible. Il s'avère que la boucle for...in fonctionne sur les chaînes

Copier le code Le code est le suivant :

var str='aa';
for(var nom en str){
console.log(nom);
console.log(str[nom])
>

C'est également possible, il divisera la chaîne et la lira selon l'indice numérique, mais dans le code source

Copier le code Le code est le suivant :

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

est limité aux tableaux et aux objets, cela n'aura donc aucun effet lors de la copie approfondie ?

Après mon test, la copie profonde est également possible, car la valeur copiée dans le code source s'est transformée en fonction anonyme

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

Quant à savoir pourquoi il s'agit d'une fonction, je ne l'ai pas encore compris et je le laisserai résoudre plus tard !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn