图片 3

新鲜目标,将函数的实际参数调换来数组的主意

有关小编:韩子迟

图片 1

a JavaScript beginner
个人主页 ·
小编的稿子 ·
9 ·
   

图片 2

值得庆幸的是,大家得以由此数组的 slice 方法将 arguments
对象转变到真正的数组:
var args = Array.prototype.slice.call(arguments);
对于slice 方法,ECMAScript 26二 中 壹五.四.4.十 Array.prototype.slice
(start, end) 章节有备注:

Others

成都百货上千时候,某些方法您以为接收的参数是数组,其实类数组也是能够的。

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

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]

为什么 IE 中 NodeList 不可能动用 [].slice.call(nodes) 方法转变呢?
In Internet Explorer it throws an error that it can’t run
Array.prototype.slice.call(nodes) because a DOM NodeList is not a
JavaScript object.

JavaScript 特殊目标 Array-Like Objects 详解

2016/06/26 · JavaScript
· Javascript,
underscore

本文笔者: 伯乐在线 –
韩子迟
。未经笔者许可,禁止转发!
接待参与伯乐在线 专辑小编。

那篇小说拖了有两周,前日来跟我们你一言笔者一语 JavaScript 中1类分外的靶子 ->
Array-Like Objects。

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

一般的函数的 arguments.length 都在 拾 以内,方法2有优势;
方法2的代码量上也比第1种少,至少能够减小一点字节 ^^

打赏帮衬自身写出更多好文章,感激!

图片 3

1 赞 3 收藏
评论

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.

Array-Like

JavaScript 中整整皆为目的,那么什么样是 Array-Like
Objects?顾名思义,正是像数组的目的,当然,数组本身即是目的嘛!稍微有点基础的同桌,一定精通arguments 正是 Array-Like Objects 的1种,能像数组同样用 [] 去访问
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福特Explorer(感激 @HangYang 同学建议)
,因为那是 JavaScript 中能准确表示的最大数字。

思想还有哪些同时能满意上述口径的?NodeList,HTML
Collections,仔细怀念,以致还有字符串,可能有所 length
属性的靶子,函数(length 属性值为形参数量),等等。

复制代码 代码如下:

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?

打赏扶助本身写出越多好文章,感激!

打赏作者

但两岸的属性差距真的留存呢?经过个人轻便测试开采:

Array-Like to Array

部分时候,须要将 Array-Like Objects 转为 Array
类型,使之能用数组的片段艺术,四个分外简单狠毒并且包容性优良的诀就算新建个数组,然后循环存入数据。

我们以 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 类型,大概为负,那么直接再次回到三个空数组,不然返回a[0]-a[length-1] 组成的数组。(具体能够看下 v八 源码

当然,ES6 提供了更省事的法子。

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;
  }
}

复制代码 代码如下:

哪些将 NodeList
(比方:document.getElementsByTagName(‘div’))转变来数组呢?

复制代码 代码如下:

复制代码 代码如下:

《Pro JavaScript Design Patterns》(《JavaScript 设计情势》)的小编Dustin Diaz 曾提议:

复制代码 代码如下:

在 arguments.length
很小的时候,方法贰性质上稍有一小点优势,而在arguments.length
很大的时候,方法壹却又稍有优势。

slice 方法将
arguments 对象调换来真正的数组: var args =
Array.prototype.slice.call(arguments); 对于slice 方法,E…

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

var args = [].slice.call(arguments, 0);
理由有2:

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;
}
}

而是对此平时来说,个人建议照旧采用第壹种方法,但其它减轻方案,未有最棒的,只有最合适:

缓和方案差不多如下:

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

聊到底附上方法三,最老土的方法: