当前位置: 永利皇宫463手机版 > Web前端 > 正文

非同一般对象

时间:2019-09-26 04:46来源:Web前端
JavaScript 特殊指标 Array-Like Objects 详解 2016/06/26 · JavaScript· Javascript,underscore 正文小编: 伯乐在线 -韩子迟。未经作者许可,禁止转发! 款待参预伯乐在线 专栏撰稿人。 那篇小说拖了有

JavaScript 特殊指标 Array-Like Objects 详解

2016/06/26 · JavaScript · Javascript, underscore

正文小编: 伯乐在线 - 韩子迟 。未经作者许可,禁止转发!
款待参预伯乐在线 专栏撰稿人。

那篇小说拖了有两周,明天来跟大家聊聊 JavaScript 中一类特殊的对象 -> Array-Like Objects。

(本文节选自 underscore 源码解读类别作品,完整版请关怀 )

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 类型,使之能用数组的某个格局,四个特别轻巧严酷并且包容性卓绝的不二等秘书诀是新建个数组,然后循环存入数据。

我们以 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(IE9- 会有标题)。

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] 组成的数组。(具体能够看下 v8 源码 )

道理当然是那样的,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,V8 下会异常的慢,具体能够看下 幸免予修业改和传递 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;
  }
}

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]

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 收藏 评论

有关小编:韩子迟

图片 2

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

图片 3

编辑:Web前端 本文来源:非同一般对象

关键词: