3

我有以下 JavaScript 代码。我已经使用 new 关键字初始化了一个数组,因此创建了一个数组对象的新实例。然后我通过向它添加元素来填充数组。

但是,我认为我犯了一个根本性的误解——代码的下一部分让我非常困惑,如果不够清楚或者完全错误,请更正我的术语。我已经登录了 (beatles.length)。我正在使用长度属性来找出数组中有多少元素。但是为什么长度是属性而不是方法呢?

难道不是长度实际上是 Array 对象可以调用的返回数值的方法吗?如果长度不是一种方法,那么为什么它是一个属性(属于数组对象的变量)?请简明扼要地解释这里的区别。

var beatles = new Array();
beatles[0] = "John";
beatles[1] = "Paul";
beatles[2] = "George";
beatles[3] = "Ringo";

console.log(beatles.length);
4

7 回答 7

3

当您将元素推送到数组对象时,该属性会增加或减少。

例如我的(假)对象:

var myArray = function(){
   this.length = 0;

   this.push = function(itm){
       this.length++; 
       // ^ doesn't do anything aside from increase length
   };
};
于 2013-01-22T17:31:10.817 回答
2

不需要.length一个函数,因为它不需要每次都重新计算,而是在你将元素推到[]对象上时根据需要增加或减少它。

虽然函数可以是幂等的,但属性总是幂等的,这也.length更适合。

函数通常会改变状态(如.push),或根据它们接收的参数返回不同的值(.slice, .splice)。

换一种说法:

初始化数组的首选方法是var a = [];,并添加您应该使用的元素a.push(element);

于 2013-01-22T17:31:36.093 回答
2

Array.length属性实际上是两个(隐藏)方法get()和一个的封装set(),也称为访问器。

get()当您在表达式中使用属性时,JavaScript 会在内部调用,例如:

var n = fields.length;

相反,它set()在分配中使用时调用,例如:

fields.length = 1;

这样做还会更新数组项以满足以下条件。

属性的值length总是比最大​​项索引高 1(如果没有,则为零);

这是一个重要的细节,因为在某些情况下,它不会与数组中的(非空)项的数量严格相同。

于 2013-01-25T08:56:11.180 回答
2

两者StringArrays都是类型Objects并且不是基本变量类型。

因此,length是泛型对象的成员变量,Object通常可用于 Array 和 String。在 String 的情况下,它返回字符串长度,在 Array 的情况下,它通过覆盖返回计数。

一个小例子是:

var a = "Hello";
var b = new Array();
b[0] = "Hello";
b[1] = "World";
a.length    // returns 5
b.length    // returns 2
于 2013-01-22T17:31:24.953 回答
1

在这种情况下,length是一个始终由 javascript 引擎本身保持有效的属性。

于 2013-01-22T17:31:31.617 回答
1

length是一个伪属性,引擎盖下有一些东西可以让它像它一样工作。

length表现得像一个 getter 和一个 setter(像一个函数)。您可以像访问属性一样访问它,但不能像属性一样删除它:(delete beatles.length将失败)。

如果将元素添加到 Array,则length属性将相应更改。

如果设置长度属性,则数组将更改 -beatles.length = 0;将清除数组。

现在没有办法自己制作类似的功能(没有使用显式的 get/setter)。其中一些将在新的 ES5(或 6?)标准中提供。就像制作不可变属性的能力一样。不过,索引分配的魔力将特定于数组,这是一种语言特性。

至于为什么语言设计者将其设为属性而不是函数......好吧,也许是性能,也许是与其他语言的相似性(当然最值得注意的是 Java)。

资源:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/get https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/set

于 2013-01-22T17:34:21.810 回答
0

它是一个属性,但它不同于整个语言中的任何其他属性

数组与您熟悉的对象类型并不完全相同(尽管它们确实非常接近)。规范定义了一种特殊类型的对象,称为Array exotic object,只是为了保持length属性按应有的方式工作,并且所有 Arrays 实际上都是这种外来对象,而不是标准对象。还有一些其他类型的奇异对象,但数组的对象是我们关心的问题。

length属性的基础看起来很简单:它是数组中元素的数量。但是要保持最新状态需要大量的幕后魔法。即使是 getter 和 setter 也无法完全处理它。

原因来自于 Arraylength属性的实际定义:如果你看一个对象的属性名称,有可能将它们中的一些表示为数字,如果可以,那么其中一个数字必须大于所有其他人。数组外来对象总是有一个名为 的属性length,并且该属性的值必须始终大于其对象的最大此类数字。如果其他属性发生更改,则数组length可能也必须更改,具体取决于其他属性的名称。所以它必须监控所有的属性变化,以确保它在它应该更新的时候更新

目前,在 JavaScript 中没有办法做到这一点。您可以使用 setter 让函数监视对特定属性的更改,但不能使用通用函数来监视对象的所有属性更改。ECMAScript 6 看起来有办法通过代理对象来做到这一点,但目前还没有任何浏览器完全支持它。

于 2014-11-06T18:06:43.780 回答