I have been working on mobile recently. Because I am familiar with jQuery, and Zepto provides the same API as jQuery, I chose Zepto as the development framework.
Since it is developed on mobile, some new APIs added to ES5 are also used, such as forEach. Here are some examples of the code I wrote:
(function(v) { return !!v; })
I naively thought that forEach is the same as each of jQuery. As long as my return value is false, it will interrupt the loop. So, I wrote 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 realized that the callback function of forEach cannot interrupt the loop, so I hung a function on it and replacedAll, perfect.
= function(fn) { var i = 0, len = ; for (; i < len; ++i) { if (fn(this[i], i) === false) { break; } } };
Until one day, I wanted to do some optimization. Considering that the json that the client needs to save is too large (I didn't lie to you, you can go to 20M at most), stringify is too time-consuming and will block the UI, so I used Worker to open a thread in the background, specifically for stringify this json, similar to this:
addEventListener("message", function(e) {
var data = ;
data = (data);
postMessage(data);
}, false);
posMesage:
(data)
However, the console outputs the following error message:
Uncaught DataCloneError: Failed to execute 'postMessage' on 'Worker': An object could not be cloned.
I'm cheating, why can't I even copy a json when I kill this day? So I started looking for the reason and found out that there is this thing in my json:
Oh my God, what the hell is this? Why did this foreach run in? I looked at the $.extend(true, {}, obj) in the editor trembled there. I couldn't help but wonder, it wasn't you who was doing it. 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 = (arguments, 1) if (typeof target == 'boolean') { deep = target target = () } (function(arg){ extend(target, arg, deep) }) return target }
Oh my God, this guy is really making trouble. Just use for...in... to traverse the array, but else if (source[key] !== undefined) target[key] = source[key] Can the conditions here be more serious? Adding hasOwnProperty to check will not waste much time. Tears flowing
After being cheated by Zepto, I immediately went to jQuery to complain, hoping that it would comfort me, but unexpectedly:
= = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, 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" && !(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 && ( (copy) || (copyIsArray = (copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && (src) ? src : []; } else { clone = src && (src) ? src : {}; } // Never move original objects, clone them target[ name ] = ( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; };
This guy is also explained else if ( copy !== undefined ) {target[ name ] = copy;}.
In the end, I had no choice but to write one by myself.
Summary: When you want to use $.extend, don't easily hang your customized properties and methods, otherwise you may have to look for bugs in the future.
The above is the entire content of this article, I hope you like it.