(JQuery | Zepto). A small problem with extend, jqueryzepto
I have been working on mobile terminals recently. I am also familiar with jQuery. In addition, Zepto provides the same API as jQuery, so I chose Zepto as the development framework.
Because it is mobile development, some new ES5 APIs are also applied, such as forEach. Below are some examples of the code I wrote:
list.forEach(function(v) { return !!v;})
I naively thought that forEach is the same as jQuery's each. As long as my return value is false, it will interrupt the loop, so, I have written a lot of traversal code like this (I am really too lazy to declare variables for each traversal)
After writing for a while, I suddenly found that the forEach callback function cannot interrupt the loop, so I hung a function on Array. prototype And then replaceAll, perfect.
Array.prototype.foreach = function(fn) { var i = 0, len = this.length; for (; i < len; ++i) { if (fn(this[i], i) === false) { break; } } };
Until one day, I want to optimize it. Considering that the json to be saved on the client is too large (you can go to 20 M without lying to you), stringify is too time-consuming and will block the UI, therefore, I use Worker to open a thread in the background for stringify json, which is similar to this:
addEventListener("message", function(e) { var data = e.data; data = JSON.stringify(data); postMessage(data);}, false);
PosMesage:
worker.postMessage(data)
However, the console outputs the following error message:
Uncaught DataCloneError: Failed to execute 'postmessage' on 'worker': An object cocould not be cloned.
Sorry, why can't I copy a json file? I began to look for the reason and found this in my json file:
Oh, my God, what is this? Why did foreach come in? I checked $ in the editor. extend (true, {}, obj) is trembling there, and I can't help wondering, it's not what you're doing. So, I checked the source code of $. 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, my God, this is really a strange thing. Just use for... in... to traverse the array. That's all, but else if (source [key]! = Undefined) target [key] = source [key] Can the conditions here be serious? Add a hasOwnProperty to check whether it will waste much time. Burst into tears
After being pitted by Zepto, I immediately complained to jQuery and hoped it could comfort me:
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;};
This product is also else if (copy! = Undefined ){Target [name] = copy;}I told you, my mother-in-law.
Finally, I had to write one myself.
Summary: When you want to use $. do not use Array. prototype and Object. the Custom Attributes and methods are attached to prototype. Otherwise, you may need to find bugs in the future.