Why does setting positions in a subclass of Array not change its length? Should I not subclass array?

前端 未结 4 1993
深忆病人
深忆病人 2021-01-19 04:56

In the CoffeeScript program below, I create a subclass of Array which sets two positions in its constructor:

class SetPositionsArray extends Arr         


        
4条回答
  •  情书的邮戳
    2021-01-19 05:11

    The simplest explanation is: length is magic.

    length obviously doesn't behave like an ordinary property, since it changes its value when you insert/delete other properties on its object (and, conversely, setting length = 0 will delete other properties); but there's nothing special about the identifier "length". That means you can easily write foo.length = 'bar', and the world will keep turning. Only on arrays does it have its special nature.

    Now, you might expect when when you extend the Array constructor, that you get an array—but do you? Well, in one sense you do:

    class PushValuesArray extends Array
    (new PushValuesArray) instanceof Array  # true
    

    Unfortunately, for the purpose of length, you don't. All the extends keyword does here is create a prototype chain, and the Array prototype has a distinctly non-magical length property:

    Array::length  # 0
    

    That's all you get on your PushValuesArray instance. Sadly, there's no way to duplicate that length magic on your own objects. Your only option is to either write a function instead (say, size()), or modify the Array prototype with the methods you want and use true arrays instead.

    To sum up: Subclassing Array won't get you very far. That's why, for instance, jQuery has a very array-like API on its objects—

    $('body').length  # 1
    $('body')[0]      # [object HTMLBodyElement]
    

    —but doesn't actually make those objects inherit from the Array prototype:

    $('body') instanceof Array  # false
    

提交回复
热议问题