JS 中数组常用方法以及它的原理实现(一)

开始

JS的数组中有很多API,其中包括很多ES6新增的方法,每个API的的传参,返回值以及是否会修该原数组有很大不同,如果能从原理角度,并且依赖js实现该方法,就可以更加熟练它的使用。下面我们就按着MDN 上的介绍依次实现。

MDN数组链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array

数组方法

Array.from

概念

Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

实现

思路:

  • 数组的静态方法,所以定义 Array._from=function(xxx){}
  • 数组,类数组对象,可迭代对象都实现 Symbol.iterator,只有实现该方法,才能实现遍历,所以我们可以依赖该方法来实现对目标对象的遍历。

Array._from=function(target,fn){
       let data=target;
       if(typeof data[Symbol.iterator]!='function')
       {
           return [];
       }
       if(typeof fn!=='function')
       {
           fn=false;
       }
       // 必须实现迭代器
       const it= data[Symbol.iterator](),res=[];
       let end=false;
       while (!end)
       {
         let {value,done}=it.next();
         if(!done)
         {
             if(fn){
                 res.push(fn(value))
             }
             else{
                 res.push(value);
             }
         }
         end=done;
       }
       return res
}

测试

let a='1111',b=10,c=new Set([1,2,3])
console.log(Object.getOwnPropertySymbols(a.__proto__)) // 
console.log(Array._from(a)) 
console.log(Object.getOwnPropertySymbols(b.__proto__)) //[] 数字没有实现遍历器,所以返回空数组
console.log(Array._from(b)) //[]
console.log(Object.getOwnPropertySymbols(c.__proto__)) //[ Symbol(Symbol.toStringTag), Symbol(Symbol.iterator) ]

注意

从测试结果可以看出 是否可以被转成数组,关键取决于目标对象原型上实现是否实现了Symbol(Symbol.iterator)

Array.isArray()

作用

Array.isArray() 用于确定传递的值是否是一个 Array。

实现

思路

  • 数组上的静态方法。定义 Array._isArray
  • 我们依赖 Object.prototype.toString 检验是否是数组。

代码

Array._isArray=function (target) {

    return Object.prototype.toString.call(target).slice(8,-1)==='Array'
    
}

测试

很简单没有多余可说的

console.log(Array._isArray([1])); //true
console.log(Array._isArray(1)); // false

Array.of

作用

Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

注意:其实和Array 区别不大,就是单个参数有所不同

Array.of(6) //[6]

Array(6) [empty × 6]

思路

  • 数组的静态方法
  • 将argument(也是类数组对象)可以使用for遍历

实现


Array._of=function(){
    console.log(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3 } 
    let arr=[];
    for(let item of arguments)
    {
        arr.push(item)

    }
    return  arr;

}

测试

Array._of(1,2,3) //[1,2,3]
Array._of(1)  //[1]

Array.prototype.concat()

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

示例

console.log([].concat(1,2)); //[ 1, 2 ]

console.log([3].concat(1,[2])); //[ 3, 1, 2 ]

console.log([].concat(1,2,[3,[4]])); [ 1, 2, 3, [ 4 ] ]

console.log(Array.prototype.concat(1,2,[3,4])) // [1,2,3,4]

思路

  • 数组原型上方法 需要 定义 Array.prototype._concat=function(){}
  • 可以合并多个对象
  • 合并对象如果是数组,会扁平化第一层。
  • 返回一个新数组,不改变原数组

我们根据如下分析来逐步实现

实现方法

Array.prototype._concat=function () {
    let target=this instanceof Array?this:[];
    //将形参转为数组(slice 下一节我们会实现)
    let args=Array.prototype.slice.call(arguments);
    //生成一个新数组
    let res=[];
    while(target.length>0)
    {
        res.push(target.shift())
    }
    //对于需要合并对象 数组
    while(args.length>0)
    {
        
        let value=args.shift();
        //扁平化
        if(value instanceof Array)
        {
            for(let item of value)
            {
                res.push(item);
            }
        }
        //直接插入
        else{
            res.push(value);
        }
    }
    return res;
}

测试

同样我们可以得到如下结果

console.log([]._concat(1,2)); //[ 1, 2 ]

console.log([3]._concat(1,[2])); //[ 3, 1, 2 ]

console.log([]._concat(1,2,[3,[4]])); //[ 1, 2, 3, [ 4 ] ]

Array.prototype.entries()

作用

entries() () 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。

keys() 方法返回一个包含数组中每个索引键的Array Iterator对象。

values() 方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值。

以上三个方法原理一样,我们在这实现entries() 方法。

思路

  • 数组原型上已经实现Symbol.iterator 遍历器方法,只需要获得它并执行就能得到

实现


Array.prototype._entries=function(){
       let arr=[];
      for(let i=0;i

测试

也没啥可多说的

const array1 = ['a', 'b', 'c'];

const iterator1 = array1._entries();

console.log(iterator1.next().value);
// expected output: Array [0, "a"]

console.log(iterator1.next().value);

结语

先总结以上五个方法,以上方法总体来说还是相对比较简单的,下一继续根据MDN上的介绍和用法依次进行总结。

掘金地址:https://juejin.im/user/5efd45a1f265da22f511c7f3/posts

你可能感兴趣的:(JS 中数组常用方法以及它的原理实现(一))