侧边栏壁纸
博主头像
woku博主等级

成功的路上并不拥挤

  • 累计撰写 50 篇文章
  • 累计创建 13 个标签
  • 累计收到 3 条评论

Array.from

woku
2021-11-22 / 0 评论 / 0 点赞 / 45 阅读 / 4,467 字

是什么?

Array上的一个静态方法

es2015 - es6版本

简单使用

const arr = [1, 2, 3]
const newArr = Array.from(arr)
console.log(newArr)
console.log(newArr === arr)  // false

newArr === arr为false,说明Array.from返回的是一个新的数组引用

const arr = [{
    id: 1
}, {
    id: 2
}]
const newArr = Array.from(arr)
console.log(newArr[0] === arr[0]) // true
console.log(newArr)

newArr[0] === arr[0]

  • newArr[0]和arr[0]都是引用类型

  • newArr[0] === arr[0] 为true说明都是同一个引用地址

  • 通过Array.from 返回的新数组是一个浅拷贝

参数

第一个参数arrayLike

  • 参数为字符串
const str = '123'
const newArr = Array.from(str)
console.log(newArr)  // ['1','2','3']

'123'字符串底层是通过String构造函数构造的,new String('123'),具有 Symbol(Symbol.iterator) 表示可迭代

可以正常输出一个数组

  • 参数是一个symbol
const sm = Symbol('123')
const newArr = Array.from(sm)
console.log(newArr)  // []

symbol表示唯一的,包装之后的仍然是一个唯一的值

const sm = Symbol('123') const sm2 = Symbol('123') sm和sm2并不相等

Array.from无法处理这种数据

Array.from 不做处理,并返回一个空数组

  • 参数是一个数字
const n = 123
const newArr = Array.from(n)
console.log(newArr)  // []

Array.from 不做处理,并返回一个空数组

  • 参数是一个boolean
const bool = true
const newArr = Array.from(bool)
console.log(newArr)  // []

Array.from 不做处理,并返回一个空数组

  • 参数是一个正则
const reg = /123/
const newArr = Array.from(reg)
console.log(newArr)  // []

Array.from 不做处理,并返回一个空数组

  • 参数是null、undefined
var newArr = Array.from(undefined)
var newArr = Array.from(null)
var newArr = Array.from()  // 不填相当于里面有个undefined

直接报错,值不合法(不是一个可迭代对象)

  • 当参数为一个普通对象
const obj = {
    a:1,
    b:2,
    c:3
}
const newArr = Array.from(obj)  
console.log(newArr)  // []
  • 参数是Map
const m = new Map([
    ['a',1],
    ['b',2],
    ['c',3]
])
const newArr = Array.from(m)
console.log(newArr)  

img

  • 参数是Set
const s = new Set([1,2,3,4,5])
const newArr = Array.from(s)
console.log(newArr)  // [1, 2, 3, 4, 5]

总结:Array.from的第一个参数必须是可迭代对象

  • 当参数为一个类数组
const arrayLike = {
    0:1,
    1:2,
    2:3,
    length:3
}
const newArr = Array.from(arrayLike)  
console.log(newArr)  // [1,2,3]
const arrayLike = {
    a: 1,
    1: 2,
    2: 3,
    length: 3
}
const newArr = Array.from(arrayLike)  
console.log(newArr)  // [undefined, 2, 3]

长度为3,键名必须从0开始,如果没有对应的下标名,那么该项值就为undefined

const arrayLike = {
    a: 1,
    1: 2,
    2: 3,
    length: 5
}
const newArr = Array.from(arrayLike)  
console.log(newArr)  // [undefined, 2, 3, undefined, undefined]

length属性决定了数组长度,属性名决定了填充该数组的位置

正常返回一个对应数组的必要条件:

1.键名必须从0开始按照顺序正确排列

2.length属性名必须正确

第二个参数mapFn

const arr = [1,2,3]
const newArr = Array.from(arr,function(item) {
    console.log(item)
})
console.log(newArr) // [undefined, undefined, undefined]

在转变的过程中,让数组的每一项进行遍历,这个函数必须要return一个值,否则返回的数组中每项都是undefined

const arr = [1,2,3]
const newArr = Array.from(arr,function(item,index) {
    return item + 1
})
console.log(newArr) // [2,3,4]

第二个参数mapFn执行原理类似于

const newArr2 = Array.from(arr).map(item => {
    return item + 1
})
console.log(newArr2)

区别在于:

Array.from的第二个参数mapFn在Array.from执行过程中,回调函数也在执行

而我们写的通过先from在map的这种方式是返回了一个新数组之后再去map

mapFn回调函数的参数(item,index)

注意回调函数没有第三个参数array(有别于数组的其他遍历方法)

由于回调函数执行的时候,Array.from还没有执行完毕,所以不存在逻辑上的新数组

第三个参数回调中this

  • 在非严格模式下,this默认指向window
const arr = [1,2,3]
const newArr = Array.from(arr,function(item,index) {
    console.log(this) // window
    return item
})
  • 在严格模式下,this默认为undefined
"use strict"
const arr = [1,2,3]
const newArr = Array.from(arr,function(item,index) {
    console.log(this) // undefined
    return item
})
  • 如果有第三个参数,函数中的this指向第三个参数
const arr = [1,2,3]
const newArr = Array.from(arr,function(item,index) {
    console.log(this) // window
    return item
},{
  a:1
})

使用Array.from的场景

  • 数组填充-序列化生成器

range函数

功能:最小为1,最大为10,每次跳2

// range(1,10,2) [1,3,5,7,9]
function range(start,stop,step) {
    return Array.from({length:(stop - start) / step + 1},function(item,index) {
        return start + (index * step)
    })
}
console.log(range(1,10,2))
  • 数组的合并与去重
function combine() {
     const arr = Array.prototype.concat.apply([],arguments)
     return Array.from(new Set(arr))
}
var m = [1, 2, 2], n = [2,3,3];
console.log(combine(m,n));  

polyfill

Array.myFrom = (function () {
      var toStr = Object.prototype.toString
      var isCallable = function (fn) {
        return typeof fn === 'function' || toStr.call(fn) === '[object function]'
      }
      var toInteger = function (value) {
        var number = Number(value)
        if (isNaN(number)) return 0
        if (number === 0 || !isFinite(number)) return number
        return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number))
      }
      var maxSafeInteger = Math.pow(2, 53) - 1
      var toLength = function (value) {
        var len = toInteger(value)
        return Math.min(Math.max(len, 0), maxSafeInteger)
      }
      return function (arrLike) {
        var callee = this
        if (arrLike == null || arrLike == undefined) {
          return new TypeError('Array.myFrom requires an array-like object - not null or undefined')
        }
        var item = Object(arrLike),
          arg2
        var mapFn = arguments.length > 1 ? arguments[1] : void undefined
        if (typeof mapFn !== 'undefined') {
          if (!isCallable(mapFn)) {
            throw new TypeError('Array.myFrom: when provided, the second argument must be a function');
          }
          if (arguments.length > 2) {
            arg2 = arguments[2]
          }
        }
        var len = toLength(item.length)
        var arr = isCallable(callee) ? Object(new callee(len)) : new Array(len)
        var step = 0
        var v = item[step]
        while (step < len) {
          if (mapFn) {
            arr[step] = typeof arg2 === undefined ? mapFn(v, step) : mapFn.apply(arg2, [v, step])
          } else {
            arr[step] = item[step]
          }
          step++
        }
        arr.length = len
        return arr
      }
})()
0

评论区