美文网首页
js基础(数组)

js基础(数组)

作者: scrollHeart | 来源:发表于2024-02-03 10:40 被阅读0次

    你知道 JS 数组有哪些方法 ?

    数组原型方法主要有以下:
    join(): 用指定的分隔符将数组每一项拼接为字符串
    push(): 向数组的末尾添加新元素
    pop(): 删除数组的最后一项
    shift(): 删除数组的第一项
    unshift(): 向数组首位添加新元素
    slice(): 按照条件查找出其中的部分元素
    splice(): 对数组进行增删改
    fill(): 方法能使用特定值填充数组中的一个或多个元素
    filter(): ‘过滤’功能
    concat(): 用于连接两个或多个数组
    indexOf(): 检测当前值在数组中第一次出现的位置索引
    lastIndexOf(): 检测当前值在数组中最后一次出现的位置索引
    every(): 判断数组中每一项都是否满足条件
    some(): 判断数组中是否存在满足条件的项
    includes(): 判断一个数组是否包含一个指定的值
    sort(): 对数组的元素进行排序
    reverse(): 对数组进行倒序
    forEach(): es5及以下循环遍历数组每一项
    map(): es6循环遍历数组每一项
    copyWithin(): 用于从数组的指定位置拷贝元素到数组的另一个指定位置中
    find(): 返回匹配的值
    findIndex(): 返回匹配位置的索引
    toLocaleString(),toString(): 将数组转换为字符串
    flat(),flatMap(): 扁平化数组
    entries(),keys(), values(): 遍历数组

    数组去重的方式有哪些?时间复杂度分别是多少?

    • 双重循环
      优点:兼容性好
      缺点: 时间复杂度O(n2)
    var array = [1,1, ‘1’, ‘2’, ‘1’, 1, 2]
    Function unique(arr){
        // res 存结果
        var res = [];
        for(var i = 0, length = arr.length; I< length; I++){
            for(var j = 0; length2 = res.length; j < length2; j++){
                if(arr[I] === res[j]){
                    break;
                }
            }
            if(j == length2){
                res.push(arr[i])
            }
        }
        return res;
    }
    
    unique(array);  // [1, ‘1’, ‘2’, 2]
    
    • indexOf方法
      优点:时间复杂度降低
      缺点:有的浏览器不支持indexOf方法,时间复杂度o(n2)
      使用 indexOf 简化内层循环
    var array = [1,1,’1’, ‘2’, ‘1’, 1,2]
    function unique(arr){
        // res 存结果
        var res = [];
        for(var I = 0, length = arr.length; I < length; I++){
            var current = arr[I];
            if(res.indexOf(current) === -1){
                res.push(current);
            }
        }
        return res;
    }
    unique(array);     // [1, ‘1’, ‘2’, 2]
    
    • 排序后去重
      思路:使用快排sort将数组排序,判断当前元素与上一个元素是否相同,相同说明重复,不同添加进res中
      优点:已经排好序的数组去重,方法效率高于使用indexOf, 时间复杂度o(n)
      缺点: 已经修改数组的顺序,同时存在去重不彻底
    var array = [1, 1, ‘1’, ‘2’, ‘1’, 1, 2]
    function unique(arr){
        // res 存结果
        var res = [];
        var sortedArray = arr.concat().sort();
        console.log(sortedArray, ‘-=-=‘)
        var current;
        for(var I = 0, length = sortedArray.length; I < length; I++){
            // 如果是第一个元素,或者是相邻元素不相同
            if(!I || current !== sortedArray[I]){
                res.push(sortedArray[I]);
            }
            current = sortedArray[I]
        }
        return res;
    }
    unique(array);    // [1, ‘1’, 1, ‘2’, 2]
    
    • 使用es5的filter(Filter + indexOf)
    var array = [1,1, ‘1’, ‘2’, ‘1’, 1, 2]
    function unique(arr){
        // res 存结果
        var res = arr.filter(function(item, index, arr){
            return arr.indexOf(item) === index;
        })
        return res;
    }
    unique(array);    // [1, ‘1’, ‘2’, 2]
    
    • 排序去重的方法(filter + sort)
      优点:很简洁,思维巧妙,使用filter简化外层循环
      缺点:不支持ie9以下的浏览器,时间复杂度o(n * 2)
    var array = [1, 1, ‘1’, ‘2’, ‘1’, 1, 2]
    
    Function unique(arr){
        // res 存结果
        var res = arr.concat().sort().filter(function(item, index, arr){
            return !index || item !== arr[index -1]
        })
        return res;
    }
    unique(array);   // [1, ‘1’, 1, ‘2’, 2]
    
    • Object键值对
    var array = [1, 1, ‘1’, ‘2’, ‘1’, 1, 2]
    function unique(arr){
        // obj 存对象
        var obj = {};
        var res = arr.filter(function(item, index, arr){
            if(obj.hasOwnProperty(item)) return false;
            else {
                return obj[item] = true;
            }
        })
        return res;
    }
    unique(array)  // [1, ‘2’]
    

    发现1和‘1’是不同的,此方法会判断是同一个值,键值对中只能是字符串,会进行一个隐式转换。和sort排序的转换是一样的,可通过typeof item + item,拼成字符串为key的值避免这个问题
    // 优化

    function unique(arr){
        // obj 存对象
        var obj = {};
        var res = arr.filter(function(item, index, arr){
            if(obj.hasOwnProperty(typeof item + item)) return false;
            else {
                return obj[typeof item + item] = true;
            }
        })
        return res;
    }
    unique(array);    // [1, ‘1’, ‘2’, 2]
    

    优点: hasOwnProperty 是对象的属性存在性检查方法,对象的属性可以基于hash表实现,对属性的方法时间复杂度达到O(1);
    Filter是数组迭代的方法,内部是一个for循环,复杂度O(n),总时间复杂度O(n)
    缺点:不兼容ie9以下浏览器

    • reduce高阶函数
      优点:高阶函数的高级用法
      缺点:兼容性问题,对象数组不能使用includes方法来检测,includes区分大小写
      includes()方法用来判断一个数组是否包含一个指定的值,根据情况,若包含则返回true,否则返回false
    Var array = [1,1,’1’,’2’,’1’,1,2]
    function unique(arr){
        let newArr = arr.reduce((pre,cur) => {
            if(!pre.includes(cur)){
                return pre.concat(cur)
            }else{
                return pre
            }
        }, []);
        return newArr;
    }
    console.log(unique(array));  // [1, ‘1’, ‘2’, 2]
    
    • es6的Set数据结构
      优点:es6语法简单高效
      缺点:兼容性问题,加上使用babel编译不是问题
    var array = [1,1,’1’,’2’,’1’, 1, 2]
    function unique(arr){
        return Array.from(new Set(arr));
        // 或用扩展运算符
        return […new Set(arr)]
    }
    unique(array);   // [1, ‘1’, ‘2’, 2]
    
    • es6的Map数据结构(es6的Map + filter)
    var array = [1,1,’1’,’2’,’1’,1,2];
    function unique(arr){
        var current = new Map();
        var res = arr.filter(function(item, index, arr){
            if(current.has(item)){
                return false;
            }else{
                return current.set(item, 1);
            }
        })
        return res;
    }
    unique(array);      // [1, ‘1’, ‘2’, 2]
    

    思路:使用map的方法set和has,用has方法来判断是否存在这个key, 若没有值将map中存一个key-value

    特殊数据类型比较事例

    var str1 = ‘1’;
    Var str2 = new String(‘1’);
    Console.log(str1 == str2);   // true
    console.log(str1 === str2);  // false
    
    console.log(null == null);    // true
    console.log(null === null);  // true
    
    console.log(undefined == undefined);    // true
    console.log(undefined === undefined);  // true
    
    console.log(NaN == NaN);   // false
    Console.log(NaN === NaN);  // false
    
    console.log(/a/ == /a/);       // false
    console.log(/a/ === /a/);     // false
    
    Console.log({} == {});      // false
    Console.log({} === {});   // false
    
    Eg: var arr = [1,2,NaN];
    Arr.indexOf(NaN);   // -1
    //原因: indexOf底层还使用=== 来进行判断,因为NaN === NaN是false, 使用indexOf 还是查不到NaN这个元素
    eg: function unique(array){
        return Array.from(new Set(array))
    }
    console.log(unique([NaN, NaN]))     // [NaN]
    

    将数组的length设置为 0,取第一个元素会返回什么?

    设置length = 0会清空数组,会返回undefined

    代码题 :用尽可能多的方法实现数组扁平化

    • 使用最基础的递归遍历方式
      思路: 使用基础遍历的方式,然后遍历item项是否为数组,若是数组递归执行扁平化函数,并把执行的结果与之前contact,若item项非数组,直接将值push到最初定义的数组中
    let array = [1, [2,34,[12,4]],23];
    Function flatten(array){
        let result = []
        for(const item of array){
            if(Array.isArray(item)){
                result = result.concat(flatten(item))
            }else{
                result.push(item)
            }
        }
        return result
    }
    Console.log(flatten(array))
    
    • 使用reduce函数进行递归操作
    function flatten(array){
        return array.reduce((pre, current, currentIndex, array) => {
            if(Array.isArray(current)){
                return pre.concat(flatten(current))
            }else{
                return pre.concat(current)
            }
        }, [])
    }
    
    • while循环结合findIndex与扩展运算符
      思路:使用while循环,判断条件,concat以后的数组中是否包含数组类型,如果包含然后使用…扩展运算符进行展开并合并
    let array = [1,[2,34,[12,4]],23]
    function flatten(array){
        while(array.findIndex((item) => Array.isArray(item) > 0)){
            array = [].concat(…array)
        }
        return array
    }
    console.log(flatten(array))
    
    • 数组强制类型转换
      思路:将数组进行强制类型转换,然后使用split分隔为数组,再转换为Number类型
    function flatten(array){
        return array.toString().split(‘,’).map(item => Number(item))  // ‘array.toString()转换后的结果1,2,34,12,4,23’
    }
    console.log(flatten(array))
    
    • 使用JSON的函数和正则表达式
      思路:先使用JSON.stringify将数组进行转换,然后使用正则匹配去掉[],在最外层增加[],最后使用JSON.parse转换
    let array = [1, [2,34, [12,4]],23];
    function flatten(array){
        let result = JSON.stringify(array);  //JSON.stringify 转换后的结果’[1,[2,34,[12,4]],23]’
        result = result.replace(/(\[|\])/g, ‘’);
        result = ‘[’ + result + ‘]’;
        return JSON.parse(result)
    }
    console.log(flatten(array))
    
    • 使用栈和扩展运算符的方式实现扁平化
      思路:创建一个栈的结构,一个空数组,然后遍历栈结构,判断若是数组,使用扩展运算符展开再次扔入栈中,若不是就往新创建的数组头部增加
    function flatten(arr){
        let res = [];
        const stack = [].concat(arr);
        console.log(‘hhh’, stack)
        while(stack.length > 0) {
            console.log(stack.length, stack)
            const item = stack.pop();
            if(Array.isArray(item){
            // 用扩展运算符展开一层
                stack.push(…item);
            }else {
                item !== undefined && res.unshift(item);
            }
        }
        return res;
    }
    console.log(flatten(array))
    
    • 使用es6中的flatten函数
      思路:直接使用es6提供的flatten函数实现扁平化flatten的语法是arr.flatten([depth]) depth可以传递数组的展开深度,(默认不填时,数值是1),即展开一层数组,Infinity代表不论多少层都展开,可设置其他整数,展开固定层数
    Let array = [1,[2,34,[12,4]],23]
    function flatten(array){
        return array.flat(Infinity)
    }
    console.log(flatten(array))
    

    什么是类数组 ?

    类数组对象,指可通过索引属性访问元素并且拥有length属性的对象
    常见的类数组:

    • arguments对象
    • DOM方法的返回结果,比如:document.getElementsByClassName()
    • jQuery对象,比如$(‘div’)

    类数组和数组的区别和联系
    相同点:

    • 都可用下标索引访问每个元素
    • 都有length属性
      不同点:
    • 数组对象类型:Array, 遍历数组可用for…in.. 和for循环
    • 类数组对象类型:Object,遍历数组只能用for循环

    类数组怎么转换为数组,说说你知道的所有方法

    类数组不具有数组所具有的API

    • Array.prototype.slice.call(arguments)该方法是arguments对象转换为数组的写法
    function list(){
        return Array.prototype.slice.call(arguments);
    }
    Var li = list(1,2,3,4)
    console.log(li).  // [1,2,3,4]
    
    • Array.from()
      es6新增方法,它可以将类数组对象和可遍历对象转为数组
    console.log(Array.from(’star’));   // [’s’, ’t’, ‘a’, ‘r’]
    
    • Array.of()
      Es6新增的Array构造函数, 用于将参数中所有值作为元素形成数组
    console.log(Array.of(1,2,3,4));     // [1,2,3,4]
    

    arguments 类数组,如何遍历类数组

    Arguments是一个对象,属性是从0开始依次递增的数字,还有callee和length属性
    遍历类数组,有3个方法:
    (1)将数组的方法应用到类数组上,可使用call和apply方法

        function foo(){
            Array.prototype.forEach.call(arguments, a=> console.log(a))
        }
    

    (2) 使用Array.from方法将类数组转化成数组:

        function foo(){     
            const arrArgs = Array.from(arguments)
            arrArgs.forEach(a => console.log(a))
        }
    

    (3) 使用展开运算符将类数组转化成数组

    function foo(){
        const arrArgs = […arguments]
        arrArgs.forEach(a => console.log(a))
    }
    

    判断数组的方式

    • 用instanceof判断(object instanceof constructor)
      Instanceof运算符可判断某个构造函数的prototype属性所指向的对象是否存在于另外一个要检测对象的原型链上
    const a = [];
    Const b = {};
    console.log(a instanceof Array); // true
    console.log(a instanceof Object); // true 在数组的原型链上能找到Object构造函数
    
    • 用constructor判断
      缺点:constructor属性可以改写
      实例化的数组拥有一个constructor属性,此属性指向生成数组的方法
    const a = [];
    console.log(a.constructor);   // function Array(){ [native code] }
    
    • 用Object的toString方法判断(Object.prototype.toString)
    const a = [‘hello’, ‘world’]
    Object.prototype.toString.call(a); // ‘[object Array]’
    Object.prototype.toString.apply(a); // ‘[object Array]’
    
    • 用Array对象的isArray方法判断(最靠谱的判断数组的方法)
    const a = [];
    Array.isArray(a);    // true
    

    兼容写法:

    If (!Array.isArray){
        Array.isArray = function(arg){
            return Object.prototype.toString.call(arg) === ‘[object Array]’
        }
    }
    

    新创建一个数组空间

    创建数组
    1.使用数组字面量表示法

    var arr4 = [];      // 创建一个空数组
    var arr5 = [20];   // 创建一个包含1项数据为20的数组
    var arr6 = [‘lily’, ‘lucy’, ’Tom’];   // 创建一个包含3个字符串的数组
    

    2.使用Array构造函数

    var arr1 = new Array();     // 创建一个空数组
    var arr2 = new Array(20);  // 创建一个包含20项的数组
    Var arr3 = new Array(‘lily’, ‘Lucy’, ‘Tom’);    // 创建一个包含3个字符串的数组
    Var array4 = new Array(’23’).  // [’23’]
    

    3.Array.of方法创建数组(es6新增)
    Array.of()方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型

    let arr = Array.of(1,2);
    console.log(arr.length); // 2
    
    Let arr1 = Array.of(3);
    console.log(arr1.length);   // 1
    console.log(arr1[0]);      // 3
    
    Let arr2 = Array.of(‘2’);
    console.log(arr2.length);  // 1
    console.log(arr2[0]);    // ‘2’
    

    4.Array.from 方法创建数组(es6新增)
    在js中将‘非数组对象转换为真正的数组’,在Es6中,将可迭代对象或者类数组对象作为第一个参数传入,Array.from()返回一个数组

    function arga(…args){.        // …args剩余参数数组,由传递给函数的实际参数提供
        let arg = Array.from(args);
        console.log(arg);
    }
    arga(‘arr1’, 26, ‘from’);  // [‘arr1’, 26, ‘from’]
    

    用过 ES6 哪些数组的方法,简述他们的特性

    • 数组去重
    var arr = [1,2,3,4,3,4]
    Var arr2 = […new Set(arr)]
    
    • 交换变量的值
    let [x,y] = [1,2];
    [y,x] = [x,y];
    console.log(y)
    
    • 获取字符串中的某个字符
    let arr = ‘hellomybo’;
    console.log(arr[3]);
    
    • 使用箭头函数代替回调函数
    let a2 = [1, 2, 3].map(x => x * x);
    console.log(a1, a2);
    
    • 合并数组
    var arr1 = [‘a’, ‘b’];
    Var arr2 = [‘c’];
    Var arr3 = [‘d’, ‘e’];
    […arr1, …arr2, …arr3]     // [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
    
    • 字符串反转
    let str = ‘12345678900987654321’
    […str].reverse().join(‘’)
    
    • 过滤需要的数值 和获得计算后的数值
      过滤:
    [‘a’, , ‘b’].filter(x => true).      // [‘a’, ‘b’]
    

    计算:

    let arr = [1,2,3,4].map(x => x+1);
    console.log(arr)
    
    • 数组降维 使用generator迭代器
    var arr = [1, [[2,3],4], [5,6]];
    var flat = function*(a) {
        var length = a.length;
        for(var I = 0; I < length; I++){
            var item = a[I];
            if(typeof item !== ’number’){
                yield* flat(item);
            } else {
                yield item;
            }
        }
    }
    
    for(var f of flat(arr)){
        console.log(f)
    }
    
    • splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目
    var arr = new Array(6)
    arr[0] = ‘George’
    arr[1] = ‘John’
    arr[2] = ’Thomas’
    arr[3] = ‘James’
    arr[4] = ‘Adress’
    arr[5] = ‘Martin’
    document.write(arr + ‘<br/>’) 
    arr.splice(2,1, ‘William’)
    document.write(arr)
    // George, John, Thomas, James, Adress, Martin
    // George, John, William, James, Adress, Martin
    
    • 置空数组
    var arr = [1,2,3,4,5,6,7,8]
    arr.length = 0;
    console.log(arr) // []
    
    • 将数组转换为对象
      使用展开运算符…
    var obj = {…arr} 
    console.log(obj). // {0: 1, 1:2, 2:3, 3:4, 4: 5, 5:6, 6:7, 7:8}
    
    • 用数据填充数组
    var yc = new Array(3).fill(‘acini’)
    console.log(yc)
    // [‘acini’, ‘acini’, ‘acini’]
    
    • 从数组中删除虚值
      在js中,虚值有 false, 0, ‘’, null, NaN, undefined 可用.filter()方法来过滤这些虚值
    var mix = [0, ‘blue’, ‘’, NaN, 90, true, undefined, false]
    Var mixture = mix.filter(Boolean)
    console.log(mixture)  // [‘blue’, 90, true]
    
    • 从数组中获取随机值
      从数组中随机选择一个值,可根据数组长度获得一个随机索引
    var arr = [’太阳光大’, ‘成功是优点的发挥’, ‘不要小看自己’,‘口说好话’,‘手心向下是助人’]
    alert(arr[Math.floor(Math.random()*arr.length)]);
    
    • 对数组中的所有值求和
      var you = [1,2,3,34,456,6]
      Var sum = you.reduce((x,y)=> x+y)

    数组中的方法如何实现 break

    1. 在for循环中想调出整个循环是break;
    let func = () => {
        for(let I = 1; I <= 5; I++){
            console.log(I);
            if(I == 3){
                break
            }
        }
    }
    func();
    // 1 
    // 2
    // 3
    

    2.使用try…catch来调出循环

    try{
        let list = [1,2,3,4,5];
        list.forEach(el =>{
        console.log(el);
            if(el == 3){
                throw new Error(‘finish’)
            }
        })
    }catch(e){
        if(e.message == ‘finish’){
            console.log(‘All finish!’)
        }else{
            console.log(e.message)
        }
    }
    

    3.every()使用return false 跳出循环(需要配合return true)
    every()返回一个boolean,判断每个元素是否符合func条件,数组里面所有的元素都符合才返回true

    let func = () => {
        let list = [1,2,3,4,5];
        list.every(el => {
            if(el == 3){
                console.log(el);
                return false;
            }else {
                console.log(el);
                return true;
            }
        })
    }
    func()
    

    4.some()使用return true 跳出循环
    some()返回一个boolean,判断是否有元素是否符合func条件,数组里面所有元素有一个符合条件就返回true

    let func = () => {
        let list = [1, 2, 3, 4, 5];
        list.some(el => {
            console.log(el);
            if(el == 3){
                return true;
            }
        })
    }
    func()
    

    5.map()不会跳出循环
    语法糖:map()返回一个新的Array, 每个元素为调用func结果,新数组长度和原来一样,逐一对原来数据每个元素进行操作
    不能终止循环,使用break会报错,用return false ,输出结果会有false, 循环不会终止
    使用return true:

    let func = () => {
        let list = [1,2,3,4,5];
        return list.map(el => {
            if(el == 3){
                return true
            }
            return el;  
        })
    }
    func()
    // [1,2,true,4,5]
    

    比较常用的数组方法 map() reduce() find() findIndex() push() .... 哪些可以改变原数组,哪些不可以改变

    • 改变原数组
      Es5:
      splice()可删除从index处开始的零个或多个元素
      sort()
      pop()删除尾部元素,返回删除的值
      push()数组尾部添加,返回新数组长度
      shift()数组头部元素删除,返回删除元素
      unshift()数组头部增加,返回新数组长度
      reverse()

      Es6:
      copyWithin()
      Fill

    • 不改变原数组方法
      es5:
      Slice, join, toLocateString, toStringin, cancat, indexOf, lastIndexOf,
      Es7:
      Includes

    Js中遍历数组并不改变原数组的方法有:
    es5:
    forEach, every, some, filter, map, reduce, reduceRight,
    Es6:
    Find, findIndex, keys, values, entries

    JS 中 filter 方法如何使用

    filter()方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
    filter()不会对空数组进行检测,不会改变原始数组

    var ages = [32, 33, 16, 40];
    function checkAdult(age){
        return age >= 18;
    }
    function myFunction(){
        document.getElementById(‘demo’).innerHTML = ages.filter(checkAdult);
    }
    32, 33, 40
    

    相关文章

      网友评论

          本文标题:js基础(数组)

          本文链接:https://www.haomeiwen.com/subject/ymonodtx.html