arrify源码分析

185 阅读3分钟

什么是arrify?

arrify是一种将任何类型的值都能转成数组的js库。

实现效果:

  1. null --> []
  2. undefined --> []
  3. '你好' --> ['你好']
  4. 55 --> [55]
  5. new Set('22') --> ['22']
  6. new Map(2) --> [2]
  7. [2, 3, 4] --> [2, 3, 4]
等等

如何使用

  1. 安装 npm install arrify
  2. 在需要使用的js文件内引入即可
   import arrify from 'arrify'; 
   console.log(arrify('222')); // ['222']
  console.log(arrify(222)); // [222]
  console.log(arrify(true)); // [true]
  console.log(arrify(null)); // []
  console.log(arrify(undefined)); // []
  let sym = Symbol(333); 
  console.log(arrify(sym)); // [Symbol(333)]
  let obj = [1, 2, 3];
  console.log(arrify(obj)); // [1, 2, 3]
  obj = {
    name: '姓名',
    age: 14
  }
  console.log(arrify(obj)); 
  // [
  //   obj = {
  //     name: '姓名',
  //     age: 14
  //   }
  // ]
  obj = new Date();
  console.log(arrify(obj)); // [Mon Jun 13 2022 16:22:55 GMT+0800 (中国标准时间)]
  obj = new Set(22);
  console.log(arrify(obj)); // Uncaught TypeError: number 22 is not iterable (cannot read property Symbol(Symbol.iterator))
  obj = new Set(['23']);
  console.log(arrify(obj)); // ['23']

如何自定义实现将一个值转成数组?

通过上面对arrify的介绍,我们知道需要对值的类型进行区分然后进行转换。可以分为以下几类:

  1. 基本数据类型:string, number, boolean
  2. 基本数据类型:null, undefined
  3. 引用数据类型:array, function, obj, date等

核心就是区分数据类型, 以及区分类数组和可迭代对象

什么是类数组对象

  • 有length属性
  • 有index属性
  • 不能使用Array.prototype上定义的方法 常见的类数组就是arguments, 可以使用Array.from将类数组转成数组

什么是可迭代对象

可迭代对象就是可以迭代的对象,通俗地解释就是内部可以循环遍历的对象。主要这几种内置的可迭代项:String, Array, TypedArray, Map, Set。 要使对象变得可以迭代,必须实现一个通过Symbol.iterator的迭代器方法。特别说明:类数组对象也是一种可迭代对象 ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。

因此结合上面我们的了解,可以这样实现:

// 特别说明,对于类数组对象或可迭代对象,如果要转成数组可以使用两种方式 
// 1. Array.from(val) 
// 2. [...val] 
function arrify(val) { 
    // null和undefined 
    if(val === null || val === undefined) { return []; } 
    // 其他基本数据类型 
        if(typeOf(val) === 'string' || typeOf(val) === 'number' || typeOf(val) === 'boolean' || typeOf(val) === 'symbol') { 
        return [val]; 
    } 
    // 类数组对象转成真正的数组 
    if(Array.isArray(Array.from(val))) {
        return [...val];
    } 
    // 可迭代对象,浅拷贝对象创建数组
    if(typeof val[Symbol.iterator] === 'function') {
        return [...val]; 
    } 
    return [val] ;
}

arrify是如何实现的?

源码地址:github.com/sindresorhu…

  export default function arrify(value) {
    if (value === null || value === undefined) {
      return [];
    }
​
    if (Array.isArray(value)) {
      return value;
    }
​
    if (typeof value === 'string') {
      return [value];
    }
​
    if (typeof value[Symbol.iterator] === 'function') {
      return [...value];
    }
​
    return [value];
  }

arrify的转换规则是

  1. null和undefined转成空数组
  2. 数组直接返回
  3. string类型属于可迭代对象,但是里面的内容不能迭代完再转成数组而是作为一个整体转成数组
  4. 可迭代对象,遍历迭代,然后浅拷贝转成数组
  5. 其他类型直接放在数组里面返回。

Symbol.iterator的使用场景?

Symbol.iterator是对象的一个属性,可以根据这个属性上找到一个方法,这个方法会构造一个迭代器来迭代这个对象的值,这个方法就是next()方法。换句话说就是只要对象有Symbol.iterator属性,那么这个对象一定是可迭代对象。 ...展开和for/of循环会自动使用它,我们也可以自定义Symbol.iterator属性为任意对象值定义自己的迭代器,会覆盖默认的迭代器。

  let obj = {
    name: '赵盼儿',
    age: 24
  };
    
  obj[Symbol.iterator] = function() {
    return {
      name: this.name,
      age: this.age,
      next() {
        if (!this.name || !this.age) {
          return { done:false, value:'' };
        } else {
          return { done:true };
        }
      }
    };
  };