>

破例目的

- 编辑:至尊游戏网站 -

破例目的

JavaScript 特殊指标 Array-Like Objects 详解

2016/06/26 · JavaScript · Javascript, underscore

正文我: 伯乐在线 - 韩子迟 。未经小编许可,禁绝转发!
应接参加伯乐在线 专辑小编。

那篇小说拖了有两周,明天来跟大家你一言小编一语 JavaScript 中大器晚成类特其他目的 -> Array-Like Objects。

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

那篇小说拖了有两周,明日来跟我们拉家常 JavaScript 中繁荣富强类特殊的指标 -> Array-Like Objects。

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_INTEGEEnclave(谢谢 @HangYang 同学建议) ,因为那是 JavaScript 中能准确表示的最大数字。

想想还应该有怎么着同不日常间能满足上述原则的?NodeList,HTML Collections,稳重怀念,以致还可能有字符串,恐怕持有 length 属性的指标,函数(length 属性值为形参数量),等等。

(本文节选自 underscore 源码解读连串文章,完整版请关切 https://github.com/hanzichi/underscore-analysis)

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

Array-Like

JavaScript 中总体皆为对象,那么如何是 Array-Like Objects?看名就能够猜到其意义,正是像数组的对象,当然,数组本人便是指标嘛!稍微有一点基础的校友,一定知道 arguments 正是 Array-Like Objects 的意气风发种,能像数组同样用 [] 去访问 arguments 的元素,有 length 属性,不过却不能够用一些数组的主意,如 push,pop,等等。

那么,什么样的元素是 Array-Like Objects?大家来探望 underscore 中对其的概念。

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中华V(感激 @HangYang 同学建议) ,因为那是 JavaScript 中能准确表示的最大数字。

思维还应该有如何相同的时间能满意以上原则的?NodeList,HTML Collections,细心思忖,以至还会有字符串,只怕具备 length 属性的对象,函数(length 属性值为形参数量),等等。

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]

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

但是那不是最温婉的,更加高雅的解法我们分明都了然了,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);

也许能够用 [] 代替 Array.prototype 节省几个字节。

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 源码 https://github.com/v8/v8/blob/master/src/js/array.js#L621-L660)

自然,ES6 提供了更省事的艺术。

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

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?

打赏帮忙小编写出越来越多好小说,多谢!

打赏我

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

1 赞 3 收藏 评论

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?

至于作者:韩子迟

图片 2

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

图片 3

本文由技术教程发布,转载请注明来源:破例目的