JavaScript 里的类数组对象

 很早以前我就知道可以把 arguments 转化为数组:[].slice.call(arguments),因为

arguments 是个类数组对象,所以才可以这么用。但是我一直不清楚什么叫做类数组对象( array-like objects)

今天看 Effective JavaScript 就有一节是专门讲这个的,感觉真是太拽了。

先看我写的一些示例代码:

a = "hello"
[].map.call(a, (e) -> e.toUpperCase()) # => [ 'H', 'E', 'L', 'L', 'O' ]
[].reduceRight.call(a, (acc, e) -> acc + e) # => 'olleh'
b = {1: "a", 2: "b", 4: "c", length: 6}
[].reduce.call(b, (acc, e) -> acc + e) # => 'abc'

 

前面那几个是操作字符串的,嗯,字符串也可以看成类数组对象。但是后面那个 b 对象居然
也是类数组对象。

看书上的解释:

 

代码如下:

So what exactly makes an object “array-like”? The basic contract of
an array object amounts to two simple rules.
It has an integer length property in the range 0...2^32 – 1.
The length property is greater than the largest index of the object.
An index is an integer in the range 0...2^32 – 2 whose string representation
is the key of a property of the object.

 

居然只有这两条简单的规则。

所以为什么 arguments, 字符串,和上面那个 b 对象可以看作类数组对象呢?

它们都有一个合法的 length 属性(0 到 2**32 - 1 之间的正整数)。
length 属性的值大于它们的最大索引(index)。
再举个例子:

 

代码如下:

b = {1: "a", 2: "b", 4: "c", length: 3}
[].reduce.call(b, (acc, e) -> acc + e) # => 'ab'

 

嗯,就不对了,成了'ab' 了,因为违反了规则2:length 属性是3,
最大索引值是4要比 length 属性大了。所以表现的不正常了。

太强大了,好像只是定义了一个接口,只要符合这个接口,就可以利用数组的所有方法。

其实不是可以利用所有方法,Array.prototype.concat
是不能用的,因为它是把两个数组连接起来,你不是数组肯定是没法用它的。

还有一个小问题是,字符串创建以后是不可变的(immutable),所以你怎么折腾它都是不可变的。

但是这本书根本就没有解释为什么是符合这两个条件就可以看成类数组对象,另外这本书的作者
是那个什么 ECMAScript 委员会的成员,所以基本还是可信的。至于为什么符合这两个条件就可以看成是类数组对象,我也不知道,谷歌搜了半天也没看到什么合理的解释。

以上所述就是本文的全部内容了,希望大家能够喜欢。

时间: 2024-04-28 07:24:58

JavaScript 里的类数组对象的相关文章

JavaScript 里的类数组对象_javascript技巧

很早以前我就知道可以把 arguments 转化为数组:[].slice.call(arguments),因为 arguments 是个类数组对象,所以才可以这么用.但是我一直不清楚什么叫做类数组对象( array-like objects) 今天看 Effective JavaScript 就有一节是专门讲这个的,感觉真是太拽了. 先看我写的一些示例代码: 复制代码 代码如下: a = "hello" [].map.call(a, (e) -> e.toUpperCase())

JavaScript中的类数组对象介绍_javascript技巧

JavaScript中,数组是一个特殊的对象,其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法.而对于一个普通的对象来说,如果它的所有property名均为正整数,同时也有相应的length属性,那么虽然该对象并不是由Array构造函数所创建的,它依然呈现出数组的行为,在这种情况下,这些对象被称为"类数组对象".以下是一个简单的类数组对象: 复制代码 代码如下: var o = {0:42,

javascript 里面的 Object Event 对象 比较

问题描述 javascript 里面的 Object Event 对象 比较 今天在写一段事件代码时发现了这个问题,请问划线处为什么输出false 源码 //获得鼠标事件 mouseup mousedown 输出你按了鼠标的 左键(0) 右键(2) 中间键(1) function getButton(e) { var ent=window.event; alert(ent==window.event); //false alert(ent==e); //false if(e) { return

Javascript学习6 - 类、对象、继承

原文:Javascript学习6 - 类.对象.继承     Javasciprt并不像C++一样支持真正的类,也不是用class关键字来定义类.Javascript定义类也是使用function关键字来完成的.     在Javascript中,可以把对象(object)定义为"属性的无序集合",每个属性存放一个原始值.对象或者函数.理解这一点非常重要. ECMAScript定义:对象由特性(attribute)构成,特性可以是原始值,可以是引用值,如果特性存放的是函数,它将被看作对

Javascript中的Array数组对象详谈

 这篇文章主要介绍了Javascript中的Array数组对象,需要的朋友可以参考下 首先数组的定义以及初始化的方法:  var myArray = new Array(1,3.1415,"love"); //这里注意myArray数组中的元素不只是同一种数据类型的元素,可以有整形,有浮点型,有字符串等等都可以.这里充分展示了javascript作为一种语言对数据类型的弱化,语言更加的随意化,简便化.就行定义对象的时候用var一样.  在此介绍的有限,同时有一些我没有给出结果,希望大家

javaScript中定义类或对象的五种方式总结_javascript技巧

第一种方式: 工厂方法 能创建并返回特定类型的对象的工厂函数(factory function). function createCar(sColor){ var oTempCar = new Object; oTempCar.color = sColor; oTempCar.showColor = function (){ alert(this.color); }; return oTempCar; } var oCar1 = createCar(); var oCar2 = createCa

javascript面向对象——定义类或对象的几种方式

从语言的视角看,面向对象的编程和面向对象的javascript绝对不是什么现代的东西:从刚开始javascript就被全面的设计为面向对象的语言 下面呢,就介绍一下,定义类或对象的几种方式: 1 工厂模式 代码如下 function createcar(iColor,iDoors,iMpg) { varoTemCar = new Object; oTemperCar.color = iColor; oTemperCar.doors = iDoors; oTempCar.mpg = iMpg; o

js将类数组对象转换成数组对象_javascript技巧

在标准浏览器中,好像只要对象存在length属性,就能把它转换为数组,但IE就不尽然. [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 接着我们看看各大类库的处理: 复制代码 代码如下: //jQuery的makeArray var makeArray = function( array ) { var ret = []; if( array != null ){ var i = array.length; // The window, strings (and functions)

javascript里的类思想

javascript <script language="javascript" runat="server">function MyFile(filename, filesize, type, datelastaccessed){ this.filename = filename; this.filesize = filesize; this.type = type; this.datelastaccessed = datelastaccessed;}