在 JavaScript 中创建类似数组的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11886578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating array-like objects in JavaScript
提问by Rocket Hazmat
In JavaScript, there are objects that pretend to be arrays (or are "array-like"). Such objects are arguments
, NodeList
s (returned from getElementsByClassName
, etc.), and jQuery objects.
在 JavaScript 中,有些对象伪装成数组(或“类数组”)。此类对象是arguments
、NodeList
s(从getElementsByClassName
等返回)和 jQuery 对象。
When console.log
ged, they appear as arrays, but they are not. I know that in order to be array-like, an object must have a length
property.
当console.log
GED,它们显示为数组,但事实并非如此。我知道为了像数组一样,一个对象必须有一个length
属性。
So I made an "object" like this:
所以我做了一个这样的“对象”:
function foo(){
this.length = 1;
this[0] = "bar";
}
var test = new foo;
When I console log(test)
, I get (as expected) a foo
object. I can "convert" it to an array using
当 I 时console log(test)
,我得到(如预期的)一个foo
对象。我可以使用
Array.prototype.slice.call(test)
But, I don't want to convert it, I want it to be array-like. How do I make an array-like object, so that when it's console.log
ged, it appears as an array?
但是,我不想转换它,我希望它像数组一样。我如何制作一个类似数组的对象,以便当它被改变时console.log
,它显示为一个数组?
I tried setting foo.prototype = Array.prototype
, but console.log(new foo)
still shows a foo
object, and not an array.
我尝试设置foo.prototype = Array.prototype
,但console.log(new foo)
仍然显示一个foo
对象,而不是一个数组。
回答by zzzzBov
Depends specifically on the console. For custom objects in Chrome's developer console, and Firebug you'll need both the length
and splice
properties. splice
will also have to be a function.
具体取决于控制台。对于 Chrome 开发者控制台和 Firebug 中的自定义对象,您将需要length
和splice
属性。splice
也必须是一个函数。
a = {
length: 0,
splice: function () {}
}
console.log(a); //[]
It's important to note, however, that there is no official standard.
然而,重要的是要注意,没有官方标准。
The following code is used by jQuery (v1.11.1) internally to determine if an object should use a for
loop or a for..in
loop:
jQuery (v1.11.1) 在内部使用以下代码来确定对象应该使用for
循环还是for..in
循环:
function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
}
if ( obj.nodeType === 1 && length ) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
Note that it's possible to have an object that appears in the console as an array ([]
) but that gets iterated over with a for..in
loop in jQuery, or an object that appears as an object in the console ({}
) but that gets iterated over with a for
loop in jQuery.
请注意,可能有一个对象在控制台中显示为数组 ( []
) 但for..in
在 jQuery 中使用循环进行迭代,或者在控制台中显示为对象 ( {}
) 但使用for
循环进行迭代在 jQuery 中。
回答by Paul Aldred-Bann
Is this any use: extended array prototype, seems like he's doing what you did and creating the prototype as an array, but including an extra method (that may or may not work, I've not tested this):
这是否有任何用途:扩展数组原型,似乎他正在做你所做的并将原型创建为数组,但包括一个额外的方法(可能有效也可能无效,我没有测试过):
var MyArray = function() {
};
MyArray.prototype = new Array;
MyArray.prototype.forEach = function(action) {
for (var i = 0, l=this.length; i < l, ++i) {
action(this[i]);
}
};
Hope it helps in some way.
希望它在某种程度上有所帮助。
回答by Bhojendra Rauniyar
The same question got into my mind as while we can use array like arguments
parameter:
我想到了同样的问题,因为我们可以使用类似arguments
参数的数组:
function arrayLike() {
console.log(typeof arguments)
console.log(arguments)
console.log(Array.from(arguments))
}
arrayLike(1,2,3)
So, let's try creating our own array-like object:
所以,让我们尝试创建我们自己的类数组对象:
let arrayLikeObject = {
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
Obviously, there's no length property defined so our arrayLikeObject
will only return an empty array. Now, let's try defining a length property:
显然,没有定义长度属性,所以我们arrayLikeObject
只会返回一个空数组。现在,让我们尝试定义一个长度属性:
let arrayLikeObject = {
length: 2,
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
What if length is set different?
如果长度设置不同怎么办?
let arrayLikeObject = {
length: 1,
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
// it will only return the value from first `0: 1`
let arrayLikeObject = {
length: 5,
0: 1,
1: 2
}
console.log(Array.from(arrayLikeObject))
// other 3 values will be printed as undefined
But, I don't want to convert it...
但是,我不想转换它...
You actually wanted to create an array, not array-like object. The array-like object must be converted like you said:
您实际上想要创建一个数组,而不是类似数组的对象。必须像您说的那样转换类数组对象:
Array.prototype.slice.call(arrayLikeObject)
// Or,
[].slice.call(arrayLikeObject)
If you do try to use array methods on array-like object, then you'll get type error:
如果您确实尝试在类数组对象上使用数组方法,那么您将收到类型错误:
let arrayLikeObject = {
length: 5,
0: 1,
1: 2
}
console.log(arrayLikeObject.sort())
Thus, to use the array methods on arrayLikeObject, we need to convert it into array as we did in preceding examples using Array.from
.
因此,要在 arrayLikeObject 上使用数组方法,我们需要像在前面的示例中使用Array.from
.
Otherwise, you simply need to create an array:
否则,您只需要创建一个数组:
let arr = [1,2] // I don't mean, you don't know
Other consideration:
其他考虑:
You can't use it as constructor:
您不能将其用作构造函数:
let arrayLikeObject = {
length: 1,
slice: function () {
return 1
}
}
console.log(new arrayLikeObject) // Type error
In the following snippet, the result will be [undefined]
as the length property is set to 1 but there's no 0
indexed property:
在以下代码段中,结果将是[undefined]
length 属性设置为 1 但没有0
索引属性:
let arrayLikeObject = {
length: 1,
slice: function () {
return 1
}
}
console.log(Array.from(arrayLikeObject))
But if you set the length to 0, then the result will be an empty array []
because we're telling that we don't have any values in this array-like object.
但是如果你将长度设置为 0,那么结果将是一个空数组,[]
因为我们告诉我们在这个类似数组的对象中没有任何值。
回答by Pawel Kwiecien
Look at this :
看这个 :
var ArrayLike = (function () {
var result;
function ArrayLike(n) {
for (var idx = 0; idx < n; idx++) {
this[idx] = idx + 1;
}
// this.length = Array.prototype.length; THIS WILL NOT WORK !
}
// ArrayLike.prototype.splice = Array.prototype.splice; THIS WILL NOT WORK !
// THIS WILL WORK !
Object.defineProperty(ArrayLike.prototype, 'length', {
get: function() {
var count = 0, idx = 0;
while(this[idx]) {
count++;
idx++;
}
return count;
}
});
ArrayLike.prototype.splice = Array.prototype.splice;
ArrayLike.prototype.multiple = function () {
for (var idx = 0 ; idx < this.length ; idx++) {
if (result) {
result = result * this[idx];
} else {
result = this[idx];
}
}
return result;
};
return ArrayLike
})();
var al = new ArrayLike(5);
al.__proto__ = ArrayLike.prototype;
console.log(al.length, al.multiple(), al);
This will display in Chrome : 5 120 [1, 2, 3, 4, 5]
这将在 Chrome 中显示:5 120 [1, 2, 3, 4, 5]