Array.prototype.concat不是通用方法反驳[译]

ECMAScript 5.1规范§15.4.4.4中说到:


代码如下:

concat函数是有意设计成通用的;它并不要求它的this值必须得是个Array对象.因此,它可以被转移到其它类型的对象上作为方法来调用.

本文中的代码都使用了[]来作为Array.prototype的快捷方式.这已经是很常用的技巧了,虽然可读性差点:你通过一个对象实例访问到了Array.prototype上的方法.但是,这样的访问方式在现代的JavaScript引擎中非常之快,以至于我怀疑,说不定在这种调用方式下,这些JavaScript引擎可能已经不再创建数组实例了.本文中所有的例子都在Firefox和V8中尝试运行过.

让我们看一下concat到底是不是个通用方法:如果它是一个通用方法,则不管this的值是一个真实数组还是个类数组对象(拥有length属性,能通过索引访问每个元素),方法的返回结果都应该是一样的.我们首先尝试在数组上调用concat方法:

代码如下:

> ["hello"].concat(["world"])
["hello", "world"]

> [].concat.call(["hello"], ["world"]) // 和上面的一样
["hello", "world"]

然后,我们使用一个类数组对象来进行上面的连接操作.结果应该是一样的.


代码如下:

> [].concat.call({ 0: "hello", length: 1 }, ["world"])
[ { '0': 'hello', length: 1 }, 'world' ]

特殊变量arguments也是一个类数组对象.结果仍然不是我们所期望的:

代码如下:

> function f() { return [].concat.call(arguments, ["world"]) }
> f("hello")
[ { '0': 'hello' }, 'world' ]

真正的通用方法应该是这样的Array.prototype.push:


代码如下:

> var arrayLike = { 0: "hello", length: 1 };
> [].push.call(arrayLike, "world")
2
> arrayLike
{ '0': 'hello', '1': 'world', length: 2 }

译者注:浏览器只是按照标准来实现,所以并不存在bug的问题.

(0)

相关推荐

  • Array.prototype.concat不是通用方法反驳[译]

    ECMAScript 5.1规范§15.4.4.4中说到: 复制代码 代码如下: concat函数是有意设计成通用的;它并不要求它的this值必须得是个Array对象.因此,它可以被转移到其它类型的对象上作为方法来调用. 本文中的代码都使用了[]来作为Array.prototype的快捷方式.这已经是很常用的技巧了,虽然可读性差点:你通过一个对象实例访问到了Array.prototype上的方法.但是,这样的访问方式在现代的JavaScript引擎中非常之快,以至于我怀疑,说不定在这种调用方式下

  • JS数组降维的实现Array.prototype.concat.apply([], arr)

    把多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,最近跟着黄轶老师学习Vue2.6.1.1版本源码时,看到源码对二维数组降维的代码,所以这里来写一篇,记录一下,加强印象 二维数组降为一维数组 循环降维 let children = [1, 2, 3, [4, 5, 6], 7, 8, [9, 10]]; function simpleNormalizeChildren(children) { let reduce = []; for (let i = 0; i < childre

  • Array.prototype.slice.apply的使用方法

    复制代码 代码如下: function test(){ //将参数转为一个数组 var args = Array.prototype.slice.apply(arguments); alert(args); } arguments在JavaScript语法中是函数特有的一个对象属性(Arguments对象),用来引用调用该函数时传递的实际参数.这个对象很象数组,拥有length属性且使用下标的形式来获取其元素,但它又并非真正的Array对象.更多关于Arguments对象的资料请参阅<JavaS

  • js使用Array.prototype.sort()对数组对象排序的方法

    本文实例讲述了js使用Array.prototype.sort()对数组对象排序的方法.分享给大家供大家参考.具体分析如下: 在讲对数组对象进行排序时,我们先来简单的了解一下Array.prototype.sort().sort方法接受一个参数--Function,function会提供两个参数,分别是两个进行比较的元素,如果元素是String类型则通过Unicode code进行比较,如果是Number类型则比较值的大小.如果比较的函数中返回1则两个元素交换位置,0和-1不交换位置.先看一个例

  • JavaScript绑定事件监听函数的通用方法

    事件绑定的3中常用方法:传统绑定.W3C绑定方法.IE绑定方法.但是,在实际开发中对于我们来讲重要的是需要一个通用的.跨浏览器的绑定方法.如果我们在互联网上搜索一下会发现许多方法,以下是比较知名的几种方法: 在开始学期下面几种方法之前,应当讨论一下,一个好的addEvent()方法应当达到哪些要求: a.支持同一元素的同一事件句柄可以绑定多个监听函数: b.如果在同一元素的同一事件句柄上多次注册同一函数,那么第一次注册后的所有注册都被忽略: c.函数体内的this指向的应当是正在处理事件的节点(

  • Array.prototype 的泛型应用分析

    题目 请说明下面语句的输出: 复制代码 代码如下: x = {shift:[].shift}; x.shift(); console.info(x.length); 如果你回答正确,那么说明你已经了解 Array 函数的泛型应用.在理解这到题目之前,我 我们首先要了解数组(Array)的 shift 定义. MDC 中已经对相关的说明描述得非常的清楚 复制代码 代码如下: shift is intentionally generic; this method can be called or a

  • Javascript中Array.prototype.map()详解

    在我们日常开发中,操作和转换数组是一件很常见的操作,下面我们来看一个实例: 复制代码 代码如下: var desColors = [],     srcColors = [         {r: 255, g: 255, b: 255 }, // White         {r: 128, g: 128, b: 128 }, // Gray         {r: 0,   g: 0,   b: 0   }  // Black     ]; for (var i = 0, ilen = sr

  • 数据排序谁最快(javascript中的Array.prototype.sort PK 快速排序)

    但是让我感到意外的是,下面有个网友回复说,javascript中的Array本身的sort方法才是最快的,比快速排序算法都快,当时看到了很是郁闷,因为当时花了好长时间在排序算法上,居然忘记了Array本身的sort方法 不过javascript中内置的sort方法真的比快速排序算法还快吗? 哈哈,测试一下不就知道了 先说一下我测试的环境 1,我的测试环境是IE6.0和firefox2.0 2,每种算法有很多种不同的实现方法,下面测试中我选择上面网友实现的快速排序算法,只是把内嵌函数搬到了外面 3

  • JavaScript中利用Array和Object实现Map的方法

    本文实例讲述了JavaScript中利用Array和Object实现Map的方法.分享给大家供大家参考.具体如下: 昨天突然看到以前别人用JavaScript实现的Map感觉很不错,但是发现有个别方法有问题,顺便完善了下,添加了 remove .indexOf .values.clear等方法. /** * @author blune68 * @version 0.1, 07/27/12 * */ function Map(){ this.keys = new Array(); this.dat

  • array.prototype.silce.call 理解分析

    Array.prototype.slice.call(thisArg[, arg1[, arg2[, ...]]])成员介绍: Array   数组对象 prototype [property]是javascript中对象的属性,用来返回对象的原型引用,可以动态的给此添加方法和属性,对象如array,object,或者用户定义的对象,详细请看这里 slice [Function]用原array对象,截取指定部分返回一个新的Array 对象,详细请看这里 call [Function]   cal

随机推荐