Maison >interface Web >js tutoriel >Un petit problème avec $.extend_jquery
J'ai travaillé sur le terminal mobile récemment. Comme je connais jQuery et que Zepto fournit la même API que jQuery, j'ai choisi Zepto comme framework de développement.
Comme il s'agit d'un développement mobile, certaines nouvelles API ES5 sont également utilisées, comme forEach. Voici quelques exemples du code que j'ai écrit :
.list.forEach(function(v) { return !!v; })
Je pensais naïvement que forEach était comme each de jQuery. Tant que ma valeur de retour était fausse, cela interromprait la boucle. J'ai donc écrit beaucoup de code de traversée comme celui-ci (j'étais vraiment trop paresseux pour l'écrire). chaque parcours). Déclarer les variables)
Après avoir écrit pendant un moment, j'ai soudainement découvert que la fonction de rappel de forEach ne peut pas interrompre la boucle, j'ai donc accroché une fonction sur Array.prototype, puis remplacéAll, parfait.
Array.prototype.foreach = function(fn) { var i = 0, len = this.length; for (; i < len; ++i) { if (fn(this[i], i) === false) { break; } } };
Jusqu'à un jour, je voulais faire un peu d'optimisation Considérant que le json que le client doit sauvegarder est trop volumineux (je ne plaisante pas, le maximum peut être de 20M), stringify prend trop de temps et bloquera le UI, j'utilise donc Worker pour ouvrir un fil de discussion en arrière-plan spécifiquement pour stringifier ce json, similaire à ceci :
posMesage :
Mais la console affiche le message d'erreur suivant :
Bon sang, pourquoi je ne peux même pas copier un json ? Alors, j'ai commencé à chercher la raison, et j'ai trouvé ce truc dans mon json :
Oh mon Dieu, qu'est-ce que c'est ? Pourquoi ce foreach est-il entré ? J'ai regardé $.extend(true, {}, obj) dans l'éditeur et je n'ai pas pu m'empêcher de me demander. , ça ne pourrait pas être toi. Tu dois causer des ennuis. J'ai donc vérifié le code source de $.extend :
function extend(target, source, deep) { for (key in source) if (deep && (isPlainObject(source[key]) || isArray(source[key]))) { if (isPlainObject(source[key]) && !isPlainObject(target[key])) target[key] = {} if (isArray(source[key]) && !isArray(target[key])) target[key] = [] extend(target[key], source[key], deep) } else if (source[key] !== undefined) target[key] = source[key] } // Copy all but undefined properties from one or more // objects to the `target` object. $.extend = function(target){ var deep, args = slice.call(arguments, 1) if (typeof target == 'boolean') { deep = target target = args.shift() } args.forEach(function(arg){ extend(target, arg, deep) }) return target }
Oh mon Dieu, ce type cause vraiment des problèmes. C'est bien d'utiliser for...in... pour parcourir le tableau, mais sinon if (source[key] !== undefined) target[key] = source [ clé] Les conditions ici peuvent-elles être plus sérieuses ? Ajouter hasOwnProperty à vérifier ne fera pas perdre beaucoup de temps. Avec des larmes coulant sur mon visage
Après avoir été trompé par Zepto, je suis immédiatement allé me plaindre sur jQuery, en espérant que cela puisse me réconforter, mais de façon inattendue :
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; };
Ce type est aussi else if ( copy !== undefined ) {target[ name ] = copy;} Dis-le-moi, ma chère mère.
Au final, je n'ai eu d'autre choix que d'en écrire un moi-même.
Résumé : lorsque vous souhaitez utiliser $.extend, n'ajoutez pas facilement vos propriétés et méthodes personnalisées à Array.prototype et Object.prototype, sinon vous devrez peut-être trouver des bugs à l'avenir.
Ce qui précède représente l’intégralité du contenu de cet article, j’espère que vous l’aimerez tous.