Creating array-like objects in JavaScript

后端 未结 5 1232
轻奢々
轻奢々 2020-12-02 15:53

In JavaScript, there are objects that pretend to be arrays (or are \"array-like\"). Such objects are arguments, NodeLists (returned from get

相关标签:
5条回答
  • 2020-12-02 16:35

    I think this is what you are looking for. Override the toString function.

    foo.prototype.toString = function()
    {
        return "[object Foo <" + this[0] +">]";
    }
    
    0 讨论(0)
  • 2020-12-02 16:36

    The same question got into my mind as while we can use array like arguments parameter:

    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:

    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.

    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:

    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 讨论(0)
  • 2020-12-02 16:49

    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]

    0 讨论(0)
  • 2020-12-02 16:50

    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.

    0 讨论(0)
  • 2020-12-02 16:51

    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.

    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:

    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.

    0 讨论(0)
提交回复
热议问题