新浦京81707con > 首页 > 将函数的实际参数转换成数组的方法,特殊对象

原标题:将函数的实际参数转换成数组的方法,特殊对象

浏览次数:117 时间:2019-05-02

JavaScript 特殊目标 Array-Like Objects 详解

2016/06/26 · JavaScript · Javascript, underscore

本文小编: 伯乐在线 - 韩子迟 。未经小编许可,禁止转发!
迎接到场伯乐在线 专栏作者。

那篇小说拖了有两周,后天来跟大家拉家常 JavaScript 中一类特殊的目的 -> Array-Like Objects。

(本文节选自 underscore 源码解读连串小说,完整版请关怀 )

值得庆幸的是,大家得以因此数组的 slice 方法将 arguments 对象转变来真正的数组:
var args = Array.prototype.slice.call(arguments);
对此slice 方法,ECMAScript 262 中 一伍.四.四.10 Array.prototype.slice (start, end) 章节有备注:

Array-Like

JavaScript 中全体皆为目的,那么怎么样是 Array-Like Objects?顾名思义,正是像数组的目标,当然,数组自己正是目的嘛!稍微有点基础的同窗,一定了解arguments 正是 Array-Like Objects 的一种,能像数组同样用 [] 去访问 arguments 的元素,有 length 属性,但是却不可能用一些数组的法子,如 push,pop,等等。

那就是说,什么样的成分是 Array-Like Objects?我们来探望 underscore 中对其的概念。

JavaScript

var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; var getLength = property('length'); var isArrayLike = function(collection) { var length = getLength(collection); return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; };

1
2
3
4
5
6
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var getLength = property('length');
var isArrayLike = function(collection) {
  var length = getLength(collection);
  return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};

一点也不细略,不是数组,可是有 length 属性,且属性值为非负 Number 类型就能够。至于 length 属性的值,underscore 给出了二个上限值 MAX_ARRAY_INDEX,其实是 MAX_SAFE_INTEGE途锐(谢谢 @HangYang 同学提议) ,因为那是 JavaScript 中能正确表示的最大数字。

寻思还有何同时能满意上述条件的?NodeList,HTML Collections,仔细考虑,以致还有字符串,可能有所 length 属性的靶子,函数(length 属性值为形参数量),等等。

复制代码 代码如下:

Array-Like to Array

有个别时候,要求将 Array-Like Objects 转为 Array 类型,使之能用数组的部分方法,1个万分轻易残酷并且包容性出色的法子是新建个数组,然后循环存入数据。

我们以 arguments 为例。

function fn() { // Uncaught TypeError: arguments.push is not a function // arguments.push(4); var arr = []; for (var i = 0, len = arguments.length; i < len; i ) arr[i] = arguments[i]; arr.push(4); // [1, 2, 3, 4] } fn(1, 2, 3);

1
2
3
4
5
6
7
8
9
10
11
12
function fn() {
  // Uncaught TypeError: arguments.push is not a function
  // arguments.push(4);
 
  var arr = [];
  for (var i = 0, len = arguments.length; i < len; i )
    arr[i] = arguments[i];
 
  arr.push(4); // [1, 2, 3, 4]
}
 
fn(1, 2, 3);

只是那不是最优雅的,更优雅的解法我们自然都晓得了,use Array.prototype.slice(IE玖- 会不正常)。

function fn() { var arr = Array.prototype.slice.call(arguments); arr.push(4); // arr -> [1, 2, 3, 4] } fn(1, 2, 3);

1
2
3
4
5
6
function fn() {
  var arr = Array.prototype.slice.call(arguments);
  arr.push(4); // arr -> [1, 2, 3, 4]
}
 
fn(1, 2, 3);

抑或可以用 [] 代替 Array.prototype 节省多少个字节。

function fn() { var arr = [].slice.call(arguments); arr.push(4); // arr -> [1, 2, 3, 4] } fn(1, 2, 3);

1
2
3
4
5
6
function fn() {
  var arr = [].slice.call(arguments);
  arr.push(4); // arr -> [1, 2, 3, 4]
}
 
fn(1, 2, 3);

壹旦非得追求品质,用 [] 会新建个数组,质量肯定未有前者,然而出于斯特林发动机的优化,那一点距离基本能够忽略不计了(所以广大框架用的就是后世)。

怎么这么能够转移?大家大约精晓下,首要的原故是 slice 方法只需求参数有 length 属性即可。首先,slice 方法赢得的结果是二个 新的数组,通过 Array.prototype.slice.call 传入的参数(要是为 a),如若未有 length 属性,恐怕 length 属性值不是 Number 类型,或然为负,那么直接重回3个空数组,不然再次回到a[0]-a[length-1] 组成的数组。(具体能够看下 v八 源码 )

当然,ES陆 提供了更方便的措施。

var str = "helloworld"; var arr = Array.from(str); // ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]

1
2
3
var str = "helloworld";
var arr = Array.from(str);
// ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]

小结下,假使要把 Array-Like Objects 转为 Array,首推Array.prototype.slice,可是由于 IE 下 Array.prototype.slice.call(nodes) 会抛出荒谬(because a DOM NodeList is not a JavaScript object),所以包容的写法如下。(但还有少数要留意的是,要是是 arguments 转为 Array,最棒别用 Array.prototype.slice,V八 下会异常慢,具体能够看下 幸免予修业改和传递 arguments 给其余措施 — 影响优化 )

function nodeListToArray(nodes){ var arr, length; try { // works in every browser except IE arr = [].slice.call(nodes); return arr; } catch(err){ // slower, but works in IE arr = []; length = nodes.length; for(var i = 0; i < length; i ){ arr.push(nodes[i]); } return arr; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function nodeListToArray(nodes){
  var arr, length;
 
  try {
    // works in every browser except IE
    arr = [].slice.call(nodes);
    return arr;
  } catch(err){
    // slower, but works in IE
    arr = [];
    length = nodes.length;
 
    for(var i = 0; i < length; i ){
       arr.push(nodes[i]);
     }  
 
    return arr;
  }
}

The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the slice function can be applied successfully to a host object is implementation-dependent.

Others

不少时候,有些方法您以为接收的参数是数组,其实类数组也是足以的。

Function.prototype.apply() 函数接收的第1个参数,其实也足以是类数组。

var obj = {0: 4, length: 2}; var arr = [1, 2, 3]; Array.prototype.push.apply(arr, obj); console.log(arr); // [1, 2, 3, 4, undefined]

1
2
3
4
var obj = {0: 4, length: 2};
var arr = [1, 2, 3];
Array.prototype.push.apply(arr, obj);
console.log(arr); // [1, 2, 3, 4, undefined]

《Pro JavaScript Design Patterns》(《JavaScript 设计格局》)的撰稿人 Dustin Diaz 曾建议:

Read More

  • How to convert a array-like object to array?
  • Advanced Javascript: Objects, Arrays, and Array-Like objects
  • JavaScript quirk 8: array-like objects
  • 什么将函数的实在参数转换来数组
  • how does Array.prototype.slice.call() work?

打赏协理自身写出更加多好小说,感谢!

打赏小编

复制代码 代码如下:

打赏扶助自身写出越来越多好文章,谢谢!

图片 1

1 赞 3 收藏 评论

instead of…
var args = Array.prototype.slice.call(arguments); // 怿飞注:下称方法一
do this…
var args = [].slice.call(arguments, 0); // 怿飞注:下称方法贰

至于作者:韩子迟

图片 2

a JavaScript beginner 个人主页 · 笔者的稿子 · 9 ·    

图片 3

但两岸的习性差距真的留存呢?经过个人轻便测试发掘:

在 arguments.length 非常的小的时候,方法二天性上稍有一小点优势,而在arguments.length 极大的时候,方法1却又稍有优势。

最终附上方法三,最老土的方式:

复制代码 代码如下:

var args = [];
for (var i = 1; i < arguments.length; i ) {
args.push(arguments[i]);
}

本文由新浦京81707con发布于首页,转载请注明出处:将函数的实际参数转换成数组的方法,特殊对象

关键词: 新浦京81707con javascript

上一篇:如何准备前端开发者面试

下一篇:没有了