繁体   English   中英

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

[英]Creating array-like objects in JavaScript

在JavaScript中,有些对象假装是数组(或者是“类似数组”)。 这些对象是argumentsNodeList (从getElementsByClassName返回等)和jQuery对象。

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

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

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

var test = new foo;

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

Array.prototype.slice.call(test)

但是,我不想转换它,我希望它像阵列一样。 我如何制作一个类似数组的对象,这样当它是console.log ,它会显示为一个数组?

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

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

a = {
    length: 0,
    splice: function () {}
}
console.log(a); //[]

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

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;
}

请注意,可以将一个对象作为数组( [] )出现在控制台中,但是在jQuery中使用for..in循环或在控制台中显示为对象的对象( {} )进行迭代但是在jQuery中使用for循环迭代了。

这有用吗: 扩展数组原型 ,看起来他正在做你做的事情,并将原型创建为数组,但包括一个额外的方法(可能或可能不工作,我没有测试过这个):

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]);
    }
};

希望它在某种程度上有所帮助。

同样的问题进入我的脑海,因为我们可以使用数组arguments参数:

 function arrayLike() { console.log(typeof arguments) console.log(arguments) console.log(Array.from(arguments)) } arrayLike(1,2,3) 

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

 let arrayLikeObject = { 0: 1, 1: 2 } console.log(Array.from(arrayLikeObject)) 

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

 let arrayLikeObject = { length: 2, 0: 1, 1: 2 } console.log(Array.from(arrayLikeObject)) 

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

 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 


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

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

Array.prototype.slice.call(arrayLikeObject)
// Or,
[].slice.call(arrayLikeObject)

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

 let arrayLikeObject = { length: 5, 0: 1, 1: 2 } console.log(arrayLikeObject.sort()) 

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

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

let arr = [1,2] // I don't mean, you don't know

其他考虑:

你不能将它用作构造函数:

 let arrayLikeObject = { length: 1, slice: function () { return 1 } } console.log(new arrayLikeObject) // Type error 

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

 let arrayLikeObject = { length: 1, slice: function () { return 1 } } console.log(Array.from(arrayLikeObject)) 

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

我想就是你要找的东西。 覆盖toString函数。

foo.prototype.toString = function()
{
    return "[object Foo <" + this[0] +">]";
}

看这个 :

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); 

这将在Chrome中显示:5 120 [1,2,3,4,5]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM