HuangHongRui / Notebook

:pencil2: Yeah.. This's My NoteBook...:closed_book:
0 stars 0 forks source link

Es6_数组[创建数组] #30

Open HuangHongRui opened 7 years ago

HuangHongRui commented 7 years ago

在Es6之前, 创建数组的方式主要分2种。

  1. 调用Array构造函数
  2. 用数组字面量语法 两种均需要列举数组中的元素,且功能非常受限。

如果想将一个类数组对象(具有数值型索引和length属性的对象)转换为数组,可选的方法也十分受限。

为了简化 Js 数组的创建过程,Es6 新增了两个方法:

  1. Array.of()
  2. Array.from()
HuangHongRui commented 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属性会被设为该值 如果传入多个值, 此时无论这些值是不是数值型, 都会变为数组的元素。 (不可能总是注意传入数据的类型, 所以存在一定的风险

HuangHongRui commented 7 years ago

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'
HuangHongRui commented 7 years ago

要用 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 会非常危险 ]

HuangHongRui commented 7 years ago

Array.of() 方法不通过 Symbol.species 属性确定返回值的类型, 它使用当前构造函数( 也就是 of()方法中的 this值 )来确认正确的返回数据的类型。

HuangHongRui commented 7 years ago

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对象里面的每个元素复制到新数组中。

HuangHongRui commented 7 years ago

开发者们发现一种只需编写极少代码的新方法。 调用原生的 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转为一个数组”。

HuangHongRui commented 7 years ago

Es6 添加了一个 语义清晰,语法简洁的新方法——Array.from()来将对象转为数组

Array.from()方法 可接受可迭代对象类数组对象作为第一个参数, 最终返回一个数组。

function doSomeThing() {
  var args = Array.from(arguments);
  console.log(args)
}

Array.from 方法 调用会基于 arguments 对象中的元素创建一个新数组, args是Array的一个实例,包含arguments对象中同位置的相同值。

Array.from() 方法也是通过 this 来确认返回数组的类型的。

HuangHongRui commented 7 years ago

映射转换

如想要进一步转换数组, 可提供一个映射函数作为 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.

HuangHongRui commented 7 years ago

也可以给 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的值)

HuangHongRui commented 7 years ago

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()方法会根据迭代器来决定转换哪个值