2

我正在开发一个 JavaScript 应用程序时注意到:使用jQuery.extend函数在与引用它们自身的对象一起使用时会有一种特殊的行为。

如果您运行脚本:

var x = new (function(){ this.self = this });
var y = {}; y.self = y;

console.log($.extend(true, {}, x))
console.log($.extend(true, {}, y))

您会注意到使用 'x' 扩展工作正常,而使用 'y' 扩展会引发堆栈溢出异常。

你能解释一下这种行为吗?

4

2 回答 2

2

区别在于对象是否是普通对象。x有一个构造函数;因此,当extend谈到 的值时self,我想 jQuery 不想对其进行深度复制,因为它不知道它可以正确地重新创建它,并且最终只得到该属性的普通、非深度复制。

y,另一方面,作为 POJO 签出,并extend认为可以对其进行深度复制,这会导致无限递归。

extend代码,上面写着“ // Recurse if we're merging plain objects or arrays

于 2013-11-13T01:50:02.943 回答
2

jQuery.extend()对普通对象和数组进行深拷贝,但不是对函数对象进行深拷贝。

由于x它是一个函数对象,因此它不会对其进行深层复制。

但由于y是一个普通对象,它确实会尝试进行深度复制并陷入无限循环。

来自 jQuery.extend()源代码:

// 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;
}

您可以看到它正在检查该属性是普通对象还是数组。函数对象也不会。

于 2013-11-13T02:16:15.183 回答