Open HuangHongRui opened 7 years ago
Es6 之所以向 Js 添加新的创建方法, 是要帮助开发者规避通过 Array 构造函数创建数组时的怪异行为 (Array 构造函数表现得与传入的参数类型及数量有些不符, 例子如下)
Code :
let items = new Array(2)
console.log(items.length) // 2
console.log(items[0]) // undefined
console.log(items[1]) // undefined
items = new Array('2')
console.log(items.length) // 1
console.log(items[0]) // '2'
items = new Array(1,2)
console.log(items.length) // 2
console.log(items[0]) // 1
console.log(items[1]) // 2
items = new Array(3, '2')
console.log(items.length) // 2
console.log(items[0]) // 3
console.log(items[1]) // '2'
如果给 Array 构造函数传入一个数值型的值, 那么数组的length属性会被设为该值 如果传入多个值, 此时无论这些值是不是数值型, 都会变为数组的元素。 (不可能总是注意传入数据的类型, 所以存在一定的风险)
Es6 通过引入 Array.of()
方法来解决这个问题。
此方法与Array构造函数的工作机制类似,只是不存在单一数值型参数值的特例。
无论有但是参数,无论参数是什么类型,
Array.of()
方法总会创建一个包含所有参数的数组。
Code 例
let items = Array.of(1, 2)
console.log(items.length) // 1
console.log(items[0]) // 1
console.log(items[1]) // 2
items = Array.of(2)
console.log(items.length) // 1
console.log(items[0]) // 2
items = Array.of('2')
console.log(items.length) // 1
console.log(items[0]) // '2'
要用 Array.of()
方法创建数组,只需传入希望在数组中包含的值。
与数组字面量的使用方法相似。
大多数时候,可用数组字面量来创建原生数组,
但如需要给一个函数传入 Array 的构造函数,
则更可能传入 Array.of()
来确保行为一致。
function createArray(arrayCreator, value) {
return arrayCreator(value)
}
let items = createArray(Array.of, value)
createArray()
接受两个参数, 1是数组创造者函数, 2是要插入数组的值
可传入 Array.of()
作为 createArray() 方法的第一个参数来创建新数组
[ 如不能保证传入的值一定不是数字,那么直接传入 Array 会非常危险 ]
Array.of()
方法不通过 Symbol.species
属性确定返回值的类型,
它使用当前构造函数( 也就是 of()
方法中的 this
值 )来确认正确的返回数据的类型。
Js 不支持直接将非数组对象转换为真是数组。
arguments
就是一种类数组对象,
如要把它当做数组使用则必须先转换该对象类型
在Es5中, 可能需要编写函数来把类数组转换为数组:Code如下
function makeArray(arrayLike) {
var result = []
for(var i = 0, len = arrayLike.length; i < len; i++) {
result.push(arrayLike[i])
}
return result
}
function doSomeThing() {
var args = makeArray(arguments)
}
此方法是动手创建一个result数组,再将arguments对象里面的每个元素复制到新数组中。
开发者们发现一种只需编写极少代码的新方法。
调用原生的 slice()
方法可以将非数组对象转换为数组。
function makeArray(arrayLike) {
return Array.prototype.slice.call(arrayLike)
}
function doSomething() {
var args = makeArray(arguments)
console.log(args)
}
等价于前面一段Code例.
将slice()
方法执行时的this值设置为类数组对象,
而slice()
对象只需数值型索引和length属性就能够正确运行,
所以任何类数组对象都能被转为数组。
尽管此段代码相比前面的例子可省很多代码,
但调用Array.prototype.slice.call(arrayLike)
时,
不能直觉地想到这是“将arrayLike转为一个数组”。
Es6 添加了一个 语义清晰,语法简洁的新方法——Array.from()
来将对象转为数组
Array.from()
方法 可接受可迭代对象或类数组对象作为第一个参数,
最终返回一个数组。
function doSomeThing() {
var args = Array.from(arguments);
console.log(args)
}
Array.from
方法 调用会基于 arguments
对象中的元素创建一个新数组,
args是Array的一个实例,包含arguments对象中同位置的相同值。
Array.from()
方法也是通过 this
来确认返回数组的类型的。
映射转换
如想要进一步转换数组, 可提供一个映射函数作为 Array.from()
的第二个参数
这函数用来将类数组对象中的每一个值转换成其他形式
最后将这些值存储在 结果数组的相应索引中
function translate() {
return Array.from(arguments, (val) => val + 1)
}
let num = translate(1, 2, 3)
console.log(num) // 2,3,4
此段代码,为Array.from()
方法传入映射函数,
使数组中的每个元素在储存前都会被加 1.
也可以给 Array.from() 方法传入第三个参数来表示映射函数的this
值
let helper = {
diff: 1,
add(val) {
return val + this.diff
}
}
function translate() {
return Array.from(arguments, helper.add, helper)
}
console.log(translate('a',2,3,5,6,'2',4,7)) // ["a1", 3, 4, 6, 7, "21", 5, 8]
例子中传入 helper.add()
作为转换用的映射函数,
由于该方法使用了 this.diff
属性,
因此需要为Array.from()
方法 添加 第三个参数来指定 this 的值。
(从而无须通过调用bind()
或其他方法/方式来指定this的值)
用 Array.from()
转换可迭代对象
Array.from()
方法可处理类数组对象 & 可迭代对象
也就是说, 此方法可将所有含有 Symbol.iterator
属性的对象转为数组:
let num = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
}
let num2 = Array.from(num, (val)=>val+1)
console.log(num2) // 2,3,4
由于num 是一个可迭代对象,因此可直接将它传入 Array.from()
来转换为数组
如果一个对象既是类数组又是可迭代的,那么Array.from()
方法会根据迭代器来决定转换哪个值
在Es6之前, 创建数组的方式主要分2种。
如果想将一个类数组对象(具有数值型索引和length属性的对象)转换为数组,可选的方法也十分受限。
为了简化 Js 数组的创建过程,Es6 新增了两个方法:
Array.of()
Array.from()