ES6 -- Array.from

Array.from

参数是一个数组
返回一个新的数组引用

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

参数是一个带有引用类型元素的数组
返回的新数组是一个浅拷贝

const arr = [
  {
    id: 1,
    name: '张三',
  },
  {
    id: 2,
    name: '李四',
  },
  {
    id: 3,
    name: '王五',
  },
];

const newArr = Array.from(arr);
console.log(newArr[1] === arr[1]);//true

如果参数是字符串

const str = '123';
const newArr = Array.from(str);
console.log(newArr );//['1', '2', '3']

如果参数是一个Symbol - Array.from 不做处理 并且返回一个空数组

const sm = Symbol('123');
const newArr = Array.from(sm);
console.log(newArr);//[]

如果参数是一个数字 - Array.from 不做处理 并且返回一个空数组

const num = 123;
const newArr = Array.from(num);
console.log(newArr); //[]

如果参数是一个布尔值 - Array.from 不做处理 并且返回一个空数组

const bool = true;
const newArr = Array.from(bool);
console.log(newArr); //[]

如果参数是一个正则 - Array.from 不做处理 并且返回一个空数组

const reg = /123/;
const newArr = Array.from(reg);
console.log(newArr); //[]

null 和 undefined 都会抛出错误

const newArr = Array.from(null);
console.log(newArr);

ES6 -- Array.from_第1张图片

const newArr = Array.from(undefined);
console.log(newArr);

在这里插入图片描述

如果什么都不填 相当于里面填了undefined

const newArr = Array.from();
console.log(newArr);

在这里插入图片描述
如果参数是一个普通对象 - Array.from 不做处理 并且返回一个空数组

const obj = {
  a: 1,
  b: 2,
  c: 3,
};
const newArr = Array.from(obj);
console.log(newArr)// []

参数是一个类数组

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike);
console.log(newArr);

在这里插入图片描述
总结类数组这种情况
正常返回一个对应的数组的必要条件
1.键名必须从0开始按数字顺序排列
2.length属性必须正确
长度决定了新数组的长度 属性名决定了填充该数组的位置

参数是map

const m = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3],
]);
console.log(m);
const newArr = Array.from(m);
console.log(newArr);

ES6 -- Array.from_第2张图片
参数是一个set

const s = new Set([1, 2, 3, 4]);
console.log(s);

const newArr = Array.from(s);
console.log(newArr);

ES6 -- Array.from_第3张图片

第二个参数

回调函数 对数组的遍历 每一次遍历必须返回一个值
进一步对每一个参数进行处理
回调函数 里有两个可选参数item,index

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike, function (item, index) {
  console.log(item, index);
  return item;
});
console.log(newArr);

ES6 -- Array.from_第4张图片
当我们不返回值的时候 打印undefined

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike, function (item, index) {
  console.log(item, index);
});
console.log(newArr);

ES6 -- Array.from_第5张图片
我们也可以对item进行其他操作返回

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike, function (item, index) {
  return item + 1;
});
console.log(newArr);

在这里插入图片描述
由于回调执行的时候 Array.from 还没有执行完毕 所以不存在逻辑上的新数组
所以无法在回调里获取到新数组本身 (有别于数组的其他遍历方法)

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike, function (item, index, arr) {
  console.log(item, index, arr);
  return item;
});

ES6 -- Array.from_第6张图片
非严格模式下 回调内部的this -> window
严格模式下 回调内部的this为undefined

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike, function (item, index, arr) {
  console.log(this);
  return item;
});

在这里插入图片描述

'use strict';
const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

const newArr = Array.from(arrLike, function (item, index, arr) {
  console.log(this);
  return item;
});

ES6 -- Array.from_第7张图片

第三个参数

更改回调内的this指向

第二个参数的执行原理

const newArr = Array.from(arrLike).map(function (item, index, arr) {
  console.log(item, index, arr);
  return item + 1;
});

console.log(newArr);

ES6 -- Array.from_第8张图片
虽然Array.from 的第二个参数的执行结果与 在面调用map相同 原理也差不多
但是内部的执行顺序是不同的 Array.from 是在执行的过程中进行遍历 所以获取不到arr
而这种方法 实在Array.from运行结束后才调用map遍历所以可以获取arr

证明from 方法的第一个参数是必填的

console.log(Array.from.length); //1

填充数组 - 序列生成器

const r = range(1, 10, 2);

function range(start, stop, step) {
  return Array.from({ length: (stop - start) / step + 1 }, function (item, index) {
    return start + index * step;
  });
}
console.log(r);//[1, 3, 5, 7, 9]

数组的合并与去重

function combine() {
  const arr = Array.prototype.concat.apply([], arguments);
  return Array.from(new Set(arr));
}

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [2, 3, 4, 5, 6];
const arr3 = [3, 4, 5, 6, 7];
console.log(combine(arr1, arr2, arr3));//[1, 2, 3, 4, 5, 6, 7]

Array.from的源码实现

参数
1.可迭代对象或者类数组
2.mapFn
3.this指向

Array.myFrom = (function () {
  const isCallable = function (fn) {
    return typeof fn === 'function' || Object.prototype.toString.call(fn) === '[object Function]';
  };
  const toInt = function (value) {
    const v = Number(value);
    if (isNaN(v)) {
      return 0;
    }
    if (v === 0 || !isFinite(v)) {
      return v;
    }
    return (v > 0 ? 1 : -1) * Math.floor(Math.abs(v));
  };
  const maxSafeInt = Math.pow(2, 53) - 1;//最大安全整数
  const toLength = function (value) {
    const len = toInt(value);
    return Math.min(Math.max(len, 0), maxSafeInt);
  };
  return function (arrayLike) {
    const caller = this;
    if (arrayLike === null) {
      throw new TypeError('Method `from` requires an array-like');
    }
    const origin = Object(arrayLike);
    let arg2;
    const mapFn = arguments.length > 1 ? arguments[1] : void undefined;
    if (typeof mapFn !== 'undefined') {
      if (!isCallable(mapFn)) {
        throw new TypeError('mapFn must be a function');
      }
      if (arguments.length > 2) {
        arg2 = arguments[2];
      }
    }
    const len = toLength(origin.length);
    const arr = isCallable(caller) ? Object(new caller(len)) : new Array(len);
    let i = 0,
      val;
    while (i < len) {
      val = origin[i];
      if (mapFn) {
        arr[i] = typeof arg2 === 'undefined' ? mapFn(val, i) : mapFn.apply(arg2, [val, i]);
      } else {
        arr[i] = val;
      }
      i++;
    }
    return arr;
  };
})();

总结

Array.from 的第一个参数必须要是可迭代对象或者是标准的类数组

你可能感兴趣的:(js,es6,javascript,前端)