jQuery.extend()的实现方式详解及实例(2)

isPlainObject = function(obj) {
        if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) {
            return false;
        }

if (obj.constructor && !hasOwn.call(obj, "constructor")
                && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
            return false;
        }

var key;
        for (key in obj) {
        }

return key === undefined || hasOwn.call(obj, key);
    },

extend = function(deep, target, options) {
        for (name in options) {
            src = target[name];
            copy = options[name];

if (target === copy) { continue; }

if (deep && copy
                    && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
                if (copyIsArray) {
                    copyIsArray = false;
                    clone = src && isArray(src) ? src : [];

} else {
                    clone = src && isPlainObject(src) ? src : {};
                }

target[name] = extend(deep, clone, copy);
            } else if (copy !== undefined) {
                target[name] = copy;
            }
        }

return target;
    };

return { extend : extend };
}();


首先是 $ =  function(){...}();这种写法,可以理解为与下面的写法类似:

复制代码 代码如下:


func = function(){...};
$ =  func();


也就是立即执行函数,并将结果赋给$。这种写法可以利用function来管理作用域,避免局部变量或局部函数影响全局域。另外,我们只希望使用者调用$.extend(),而将内部实现的函数隐藏,因此最终返回的对象中只包含extend:

复制代码 代码如下:


return { extend : extend };


接下来,我们看看extend函数与之前的区别,首先是多了这句话:

复制代码 代码如下:


if (target === copy) { continue; }


这是为了避免无限循环,要复制的属性copy与target相同的话,也就是将“自己”复制为“自己的属性”,可能导致不可预料的循环。

然后是判断对象是否为数组的方式:

复制代码 代码如下:


   type = function(obj) {
        return obj == null ? String(obj) : class2type[toString.call(obj)] || "object";
   },
   isArray = Array.isArray || function(obj) {
        return type(obj) === "array";
    }


如果浏览器有内置的Array.isArray 实现,就使用浏览器自身的实现方式,否则将对象转为String,看是否为"[object Array]"。

最后逐句地看看isPlainObject的实现:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdgzxg.html