在JavaScript中创建类似于数组的对象

Roc*_*mat 19 javascript arrays object

在JavaScript中,有些对象假装是数组(或者是"类似数组").这些对象是arguments,NodeLists(从getElementsByClassName等等返回)和jQuery对象.

当console.logged时,它们显示为数组,但它们不是.我知道,为了像数组一样,对象必须具有length属性.

所以我做了一个像这样的"对象":

function foo(){
    this.length = 1;
    this[0] = "bar";
}

var test = new foo;
Run Code Online (Sandbox Code Playgroud)

当我console log(test),我得到(如预期)一个foo对象.我可以使用它将其"转换"为数组

Array.prototype.slice.call(test)
Run Code Online (Sandbox Code Playgroud)

但是,我不想转换它,我希望它像阵列一样.如何制作类似于数组的对象,以便在console.log它出现时,它会显示为数组?

我尝试过设置foo.prototype = Array.prototype,但console.log(new foo)仍显示一个foo对象,而不是一个数组.

zzz*_*Bov 28

具体取决于控制台.对于Chrome开发人员控制台和Firebug中的自定义对象,您将需要length和splice属性.splice也必须是一个功能.

a = {
    length: 0,
    splice: function () {}
}
console.log(a); //[]
Run Code Online (Sandbox Code Playgroud)

然而,重要的是要注意,没有官方标准.

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,可能有一个对象在控制台中显示为一个数组([]),但是for..in在jQuery中使用循环迭代,或者在控制台({})中显示为对象的对象但是通过for循环迭代在jQuery中.

  • 无论如何,它只是一个`console`实现的错觉.毕竟,ECMAscript中没有**'Array`(当我们忘记了TypedArrays时). (2认同)

Bho*_*yar 5

当我们可以使用类似数组的参数时,我想到了同样的问题arguments:

function arrayLike() {
  console.log(typeof arguments)
  console.log(arguments)
  console.log(Array.from(arguments))
}
arrayLike(1,2,3)
Run Code Online (Sandbox Code Playgroud)

那么,让我们尝试创建我们自己的类似数组的对象:

let arrayLikeObject = {
  0: 1,
  1: 2
 }
 
 console.log(Array.from(arrayLikeObject))
Run Code Online (Sandbox Code Playgroud)

显然,没有定义 length 属性,因此我们arrayLikeObject只会返回一个空数组。现在,让我们尝试定义一个长度属性:

let arrayLikeObject = {
  length: 2,
  0: 1,
  1: 2
 }
 
 console.log(Array.from(arrayLikeObject))
Run Code Online (Sandbox Code Playgroud)

如果长度设置不同怎么办?

let arrayLikeObject = {
  length: 1,
  0: 1,
  1: 2
 }
 
 console.log(Array.from(arrayLikeObject))
 // it will only return the value from first `0: 1`
Run Code Online (Sandbox Code Playgroud)

let arrayLikeObject = {
  length: 5,
  0: 1,
  1: 2
 }
 
 console.log(Array.from(arrayLikeObject))
 // other 3 values will be printed as undefined
Run Code Online (Sandbox Code Playgroud)


但是,我不想转换它......

您实际上想要创建一个数组,而不是类似数组的对象。类似数组的对象必须像您所说的那样进行转换:

Array.prototype.slice.call(arrayLikeObject)
// Or,
[].slice.call(arrayLikeObject)
Run Code Online (Sandbox Code Playgroud)

如果您尝试在类似数组的对象上使用数组方法,那么您将收到类型错误:

Array.prototype.slice.call(arrayLikeObject)
// Or,
[].slice.call(arrayLikeObject)
Run Code Online (Sandbox Code Playgroud)

因此,要在 arrayLikeObject 上使用数组方法,我们需要将其转换为数组,就像我们在前面的示例中使用Array.from.

否则,您只需创建一个数组:

let arr = [1,2] // I don't mean, you don't know
Run Code Online (Sandbox Code Playgroud)

其他考虑:

您不能将其用作构造函数:

let arrayLikeObject = {
  length: 5,
  0: 1,
  1: 2
 }

 console.log(arrayLikeObject.sort())
Run Code Online (Sandbox Code Playgroud)

在下面的代码片段中,结果将是[undefined]length 属性设置为 1 但没有0索引属性:

let arr = [1,2] // I don't mean, you don't know
Run Code Online (Sandbox Code Playgroud)

但如果将长度设置为 0,那么结果将是一个空数组[],因为我们告诉我们在这个类似数组的对象中没有任何值。