当我注意到这一点时,我正在开发一个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例外。
你能解释一下这种行为吗?
答案 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;
}
您可以看到它正在检查属性是普通对象还是数组。函数对象也不会。