jQuery.extend使用自引用抛出堆栈溢出异常

时间:2013-11-13 01:44:54

标签: javascript jquery stack-overflow extend

当我注意到这一点时,我正在开发一个JavaScript应用程序:使用 jQuery.extend 函数时,如果对象使用了自己的引用,则会有一种特殊的行为。

如果您运行this脚本:

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

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

您会注意到,使用'x'进行扩展可以正常工作,而使用'y'进行扩展会导致stack overflow例外。

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

2 个答案:

答案 0 :(得分:2)

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

另一方面,

y作为POJO检出,extend认为可以对其进行深层复制,从而导致无限递归。

查看extend code,其中显示“// Recurse if we're merging plain objects or arrays

答案 1 :(得分: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;
}

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