Arrays
ES6对数组添加了一些新的方法,另外还添加了TypedArray类型,这种类型支持对内存的操作,ArrayBuffer
和C语言内存分配一样,分配一块内存块。下面从以下几个方面来看看ES6数组的变化:
- 2个静态方法
Array.of()
,Array.from()
;
- 数组原型上新添加的方法
find()
,findIndex()
,fill()
,copyWithin()
;
- 新类型
ArrayBuffer
;
- Typed Arrays, 以及和Array的相同性,差异性
一.Array.of() & Array.from()
1.Array.of()
ES6新添加了这个静态方法,用于数组构造器实例化数组。我们知道数组实例化一般可以通过构造器或者数组字面量的形式来声明。ES5通过构造器声明数组会出现一个比较模糊的地方,比如:
var arr = new Array(1, 2, 3);
// 表示声明一个数组元素为[1, 2, 3]的数组
arr.length; // 3
arr[0]; // 1
arr[1]; // 2
arr[2]; // 3
var arr = new Array(2); // 2表示长度
// 而这样则表示一个数组长度为2的数组,而数组元素未声明
arr.length; // 2
arr; // [undefined, undefined]
而Array.of()
则消除了这种模糊,凡是向方法中添加数字,都表示数组元素,而不是长度
var arr = Array.of(1, 2);
arr; // [1, 2]
var arr = Array.of(2); // 2表示元素
arr; // [2]
2.Array.from()
ES6之前要将一个array-like
对象转换成数组,我们一般是利用slice
方法,比如
function doSomething() {
// 将arguments类数组对象转换成数组
var args = Array.prototype.slice.call(arguments);
// 或者 [].slice.call(arguments)
// ...
}
ES6通过静态方法 Array.from()
可以将 类数组对象 或者 可迭代的对象 转换成一个数组,其语法为:
Array.from(arraylike[, callback] [, thisArg])
上面的例子可以写为:
function doSomething() {
var args = Array.from(arguments);
// ...
}
将可迭代的对象转变为数组:
var set = new Set([1, 2, 2, 4, 5]);
// Set {1, 2, 4, 5}
var arr = Array.from(set); // [1, 2, 4, 5]
后面添加回调函数, 如果回调函数属于一个对象, 则可以添加第3个可选参数,指出this
上下文:
let helper = {
diff: 1,
add(value) {
return value + this.diff;
}
}
function translate() {
// 第2个参数为callback, 第3个参数为上下文
return Array.from(arguments, helper.add, helper);
}
translate(1, 2, 3); // [2, 3, 4]
二.新添加的方法
1.find(),findIndex()
以前我们查看数组中是否存在某个值或者某个值的位置时,一般使用indexOf()
, lastIndexOf()
,ES6添加了find(), findIndex()来添加条件查找。这两个方法和map(),forEach()一样添加一个回调函数,有选择性的添加thisArg
指定上下文。
find找到了就返回第一个满足条件的,未找到返回undefined, findIndex返回索引位置,未找到返回 -1:
var arr = [1, 2, 19, 16];
arr.find(v => v > 10 ); // 返回 19
arr.findIndex(v => v > 10); // 返回 2
find(), findIndex()用于查找一个数组元素满足某个条件而不是值,要根据值查找建议使用indexOf(), lastIndexOf().
2.fill(), copyWithin()
这两个方法其实为了操作Typed Array对象使用的,但是为了保持一致性,也添加给普通数组了。看下语法:
fill(value[,startFillPostion = 0 ] [, endFillPostion = arr.length])
copyWithin(StartToBeCopiedPos[,StartCopyPos = 0] [,EndCopyPos = arr.length])
先看fill:
var arr = [1, 2, 3, 4];
// 不指定开始和结束填充的位置
arr.fill(5); // arr: [5, 5, 5, 5]
// 指定开始
arr.fill(5, 2); // arr: [1, 2, 5, 5]
// 都指定,不包含结束位置
arr.fill(5, 0, 2)// arr: [5, 5, 3, 4]
// 当然起始和结尾也可以为负数,相当于加上数组长度
arr.fill(5, -3); // arr: [1, 5, 5, 5]
// 相当于 arr.fill(5, -3+4)
copyWith: 比较绕, 它是指复制自身内容到指定的位置:
var arr = [1, 10, 15, 29, 18];
// 只有一个参数表示被复制的索引,另外2个参数则默认从0开始到结束
arr.copyWithin(2); // arr [1, 10, 1, 10, 15]
// 2个参数,指定自身复制的位置
arr.copyWithin(3, 1); // arr [1, 10, 15, 10, 15]
// 3个参数都指定
arr.copyWithin(2, 0, 1); // arr [1, 10, 1, 29, 18]
// 0-1只有一个数 "1", 所有索引位置为2的 "15" 被替换成 "1"
上面例子我们可以发现,是有这些方法都会改变数组自身
三.ArrayBuffer
AarryBuffer是指分配内存中的一块位置用于操作,相当于C语言中的malloc(),对内存块进行二进制操作,会极大的提升性能,满足一些特别的接口要求。
先了解一下内存分配的基本语法:
var buffer = new ArrayBuffer(bytes);
比如:分配10个字节(byte)
var buffer = new ArrayBuffer(10);
内存的大小确定之后是不能修改的,可以改变内部内容
属性: byteLength
, slice()
slice方法是从已经存在的内存块中复制一段,添加都新的内存块中
var buffer = new ArrayBuffer(10);
var buffer2 = buffer.slice(3, 5);
// 将buffer中的3, 4字节内容拷贝到新的内存块中
console.log(buffer2.byteLength); // 2
四.TypedArray, Views视图
光有内存块,而不进行操作也是没有用的,javascript通过视图的方式对内存块进行读写,存在两种视图:
-
TypedArray: 特定类型的数据类型,特定类型的一种视图,对特定类型操作性能更高;
- DataView: 各种数据类型都可以,还可以指定大端序(BIG_ENDIAN),小端序(LITTLE_ENDIAN),功能更强大的一种视图
1.共同属性
这两种视图拥有一些共同的属性:
-
buffer
: 表示指向的内存块;
2.DataView
DataView构造器能够添加三个参数:new DataView(buffer[, byteOffset][, byteLength])
var buffer = new ArrayBuffer(10);
// 指向整个内存块
var dataView1 = new DataView(buffer);
dataView1.buffer === buffer; // true
dataView1.byteOffset; // 0
dataView1.byteLength; // 10
// 表示 字节 5, 6上的视图
var dataView2 = new DataView(buffer, 5, 2);
dataView2.buffer === buffer; // true
dataView2.byteOffset; // 5
dataView2.byteLength; // 2
3.TypedArray
TypedArray本质上是一个抽象类,他表示9中特定类型: Int8Array
, Uint8Array
, Int16Array
, Uint16Array
, Int32Array
, Uint32Array
, Float32Array
,
Float64Array
,还有一种只针对Canvas颜色值的 Uint8ClampedArray
具体使用方法参见阮一峰大神的博客: 二进制数组
总结
总的来说,ES6数组的变化还是很大的,新添加的方法和类型使得数组更加的强大,TypedArray,ArrayBuffer,DataView等API的添加对一些需要二进制操作的接口提供了原生的支持,像canvas, webGL, file, websocket等,这些还需再日后的使用中总结提炼。