Array.prototype 的方法在使用 jQuery.extend 深度克隆后显示为数组的键
Methods of Array.prototype appear as keys of array after deep cloning with jQuery.extend
假设数组原型已经增加了一些辅助函数:
Array.prototype.doSomething = function() { ... }
当我将一个简单数组注销到控制台时...
console.dir([1,2,3]);
...我得到:
Array [3]
0: 1
1: 2
2: 3
length: 3
__proto__: Array[0]
doSomething: function()
到目前为止一切看起来都很好。
但是一旦我使用 $.extend 深度克隆数组(深度克隆因为我的实际数据更复杂 - 一个以数组作为属性的对象,但它在任何情况下都会发生)...
$.extend(true, [], [1,2,3]);
我突然得到:
Array [3]
0: 1
1: 2
2: 3
doSomething: function() // ???
length: 3
__proto__: Array[0]
doSomething: function()
看起来原型方法已添加为数组实例的实际项。
在复制之前 JQuery.extend 是否没有测试 hasOwnProperty(),还是我做错了什么?
这似乎是文档中 $.extend 规范的一部分:
"However, properties inherited from the object's prototype will be copied over."
Does JQuery.extend not test for hasOwnProperty() before copying
不,它没有。从源代码来看,它使用 for ... in
循环来遍历正在克隆的任何内容的属性,但在设置属性之前不进行 hasOwnProperty
检查。
https://github.com/jquery/jquery/blob/7103d8ef47e04a4cf373abee0e8bfa9062fd616f/src/core.js#L120
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[ 0 ] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
// Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
target = {};
}
// Extend jQuery itself if only one argument is passed
if ( i === length ) {
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 && ( 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;
}
}
}
}
// Return the modified object
return target;
};
它会影响你的阵列数据吗?根据您使用数组的方式,可能不会。只要您使用正确的循环过程,迭代数组元素仍然是相同的。意思是 for(;;)
、for ... of
或 .forEach
。做 JSON.stringify
仍然会给你正确的 JSON.
假设数组原型已经增加了一些辅助函数:
Array.prototype.doSomething = function() { ... }
当我将一个简单数组注销到控制台时...
console.dir([1,2,3]);
...我得到:
Array [3]
0: 1
1: 2
2: 3
length: 3
__proto__: Array[0]
doSomething: function()
到目前为止一切看起来都很好。
但是一旦我使用 $.extend 深度克隆数组(深度克隆因为我的实际数据更复杂 - 一个以数组作为属性的对象,但它在任何情况下都会发生)...
$.extend(true, [], [1,2,3]);
我突然得到:
Array [3]
0: 1
1: 2
2: 3
doSomething: function() // ???
length: 3
__proto__: Array[0]
doSomething: function()
看起来原型方法已添加为数组实例的实际项。
在复制之前 JQuery.extend 是否没有测试 hasOwnProperty(),还是我做错了什么?
这似乎是文档中 $.extend 规范的一部分:
"However, properties inherited from the object's prototype will be copied over."
Does JQuery.extend not test for hasOwnProperty() before copying
不,它没有。从源代码来看,它使用 for ... in
循环来遍历正在克隆的任何内容的属性,但在设置属性之前不进行 hasOwnProperty
检查。
https://github.com/jquery/jquery/blob/7103d8ef47e04a4cf373abee0e8bfa9062fd616f/src/core.js#L120
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { 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 && ( 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; } } } } // Return the modified object return target; };
它会影响你的阵列数据吗?根据您使用数组的方式,可能不会。只要您使用正确的循环过程,迭代数组元素仍然是相同的。意思是 for(;;)
、for ... of
或 .forEach
。做 JSON.stringify
仍然会给你正确的 JSON.