JavaScript面试题分享

518 阅读4分钟

Js面试题分享

1. 数组去重(11组方法)

利用includes

function newArr(arr) {
            var array = [];
            for (var i = 0; i < arr.length; i++) {
                if (!array.includes(arr[i])) {     //includes 检测数组是否有某个值
                    array.push(arr[i]);
                }
            }
            return array
        }

Es6 利用Set方法去重(Es6中最常用)

我们可以利用Set的特性:对象存储的值总是唯一的来实现数组去重(其中一种作用)

function unique(arr) {
            console.log(new Set(arr));
            return Array.from(new Set(arr))
        }
        console.log(unique(arr))

利用for嵌套for,然后splice去重(ES5中最常用)

function unique(arr) {
            for (var i = 0; i < arr.length; i++) {
                for (var j = i + 1; j < arr.length; j++) {
                    if (arr[i] == arr[j]) {         //如果第一个等同于第二个,splice方法删除第二个
                        arr.splice(j, 1);
                        j--;
                    }
                }
            }
            return arr;
        }
        console.log(unique(arr))

利用indexOf去重

这个方法和第一个includes的做法差不多,就只有使用的方法不一样

function unique(arr) {
            var array = [];
            for (var i = 0; i < arr.length; i++) {
                if (array.indexOf(arr[i]) === -1) {
                    array.push(arr[i])
                }
            }
            return array;
        }
        console.log(unique(arr))

利用Sort 排序去重

function unique(arr) {
            arr = arr.sort()
            var arrry = [arr[0]];
            for (var i = 1; i < arr.length; i++) {
                if (arr[i] !== arr[i - 1]) {
                    arrry.push(arr[i]);
                }
            }
            return arrry;
        }
        console.log(unique(arr))

利用hasOwnProperty

利用hasOwnProperty 判断是否存在对象属性

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
    console.log(unique(arr))

利用filter

function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item, 0) === index;
  });
}
console.log(unique(arr))

利用递归去重

function unique(arr) {
        var array= arr;
        var len = array.length;

    array.sort(function(a,b){   //排序后更加方便去重
        return a - b;
    })

    function loop(index){
        if(index >= 1){
            if(array[index] === array[index-1]){
                array.splice(index,1);
            }
            loop(index - 1);    //递归loop,然后数组去重
        }
    }
    loop(len-1);
    return array;
}
console.log(unique(arr))

利用Map数据结构去重

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true); 
    } else { 
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  } 
  return array ;
}
console.log(unique(arr))

利用reduce + includes去重

function unique(arr){
    return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
console.log(unique(arr));

[...new Set(arr)]

[...new Set(arr)]

2.随机数排序

用js实现随机选取10~100之间的10个数字,存入一个数组,按从小到大排序

function getRandom(min, max, total) {
    let arr = []
    for (let i = 0; i < total; i++) {
        // 循环total次,将生成的随机数加入arr
        arr.push((Math.floor(Math.random() * (max - min + 1) + min)))
    }
    // 去重
    let arr2 = Array.from(new Set(arr))
    // 保证数字有10个
    if (arr2.length <= 9) {
        arr2 = getRandom(min, max, total)
        return arr2
    } else {
        return arr2
    }
}

let newArr = getRandom(10, 100, 10)
// sort排序
newArr.sort((a, b) => {
    return a - b
})
console.log(newArr);

3.字符串翻转(2种方式)

请自定义一个函数,实现字符串的反转

方法1:

let str = 'lajsdkljkjelka'
function Fan(string) {
    return string.split('').reverse().join('')
}
var str2 = Fan(str)
console.log(str2);

方法2:

function revStr(str){
    // 容器
    var reStr = ""
    // 排序
    for(let i = str.length - 1 ; i >= 0 ; i--){
        // 将字符串从后以此赋值 charAt()
        reStr += str.charAt(i)
    }
    return reStr
}
let str = 'lajsdkljkjelka'
console.log(revStr(str2));

4.斐波那契数列(递归与不递归)

不递归:

function fn(total){
    let a = 1 , b = 1 , c = 0
    for(let i = 1 ; i <= total ; i++){
        // 判断是否是前两项
        if(total <= 2){
            c = 1
        }else{
            // 操作 a,b 的值换成新值
            a = b
            b = c
            c = a + b
        }
    }
    return c
}

let res = fn(3)
console.log(res);

递归:

function fn(n){
    if(n==1 || n==2){
        return 1;
    }else {
        return fn(n-1)+fn(n-2);
    }
}

5. 统计次数

(注:用面向对象的方式实现,用for循环进行排序)

[1, 4, 2, 1, 3, 2, 1, 4] 作为参数(参数可变)传入js方法中,控制台输出如下结果

1 出现了 32 出现了 24 出现了 23 出现了 1

解决:

let newArr = [2,2,1,4,3,2,2,1]
function fn(arr){
    let obj = {}
    arr.forEach(e=>{
        if(obj[e]){
            obj[e]++
        }else{
            obj[e] = 1
        }
    })

    let newArr = []
    for(let key in obj){
        let obj2 = {num:key , const : obj[key]}
        newArr.push(obj2)
    }
    newArr.sort((a,b)=>{
        return b.const-a.const
    })
    console.log(newArr);

    for(let k in obj){
        console.log(`${k} 出现了 ${obj[k]} 次`);
    }
}
fn(newArr)

6.二维数组行转列(两种方式)

实现效果:

let arr = [
  ['前端','3人','8-15k','本科'],
  ['后端','5人','10-25k','研究生'],
  ['UI','2人','9-11k','大专'],
  ['ETL工程师','10人','6-12k','大专'],
];
//转换 =>
let newArr = [
  ['前端','后端','UI','ETL工程师'],
  ['3人','5人','2人','10人'],
  ['8-15k','10-25k','9-11k','6-12k'],
  ['本科','研究生','大专','大专'],
];

方法1:

let arr = [
  ['前端','3人','8-15k','本科'],
  ['后端','5人','10-25k','研究生'],
  ['UI','2人','9-11k','大专'],
  ['ETL工程师','10人','6-12k','大专'],
];
let newArr = [];
        // 遍历行  arr[0]
        for (let i = 0; i < arr[0].length; i++) {
            // 列的初始化
            newArr[i] = [];
            // 列转行
            for (let j = 0; j < arr.length; j++) {
                // 预期数据类型: 
                //     [
                //         ["前端", "后端", "UI", "ETL工程师"]
                //         []
                //         []
                //         []
                //     ]
                // 4. 列数据 塞进 行内
                newArr[i][j]= arr[j][i];
            }
        }

        console.log(newArr);

方法2:

let arr = [
  ['前端','3人','8-15k','本科'],
  ['后端','5人','10-25k','研究生'],
  ['UI','2人','9-11k','大专'],
  ['ETL工程师','10人','6-12k','大专'],
];
let newArr = arr[0].map((h,i)=>arr.map(l => l[i]))
// 或者是:
let newArr = arr[0].map((col, index) => {
            // 这个return 类似于 newArr[i] = [];
            return arr.map(row=>{
                // 这里return 类似于  ["前端", "后端", "UI", "ETL工程师"]
                return row[index];
            })
        })

7. 对象转数组(3种方法)

需求: 请把下列的数组变成是: [['苹果','胡萝卜', '花生'], ['梨', '西芹', '坚果']....]

var basket = [
            { fruit: "苹果", veg: "胡萝卜", nut: "花生" },
            { fruit: "梨", veg: "西芹", nut: "坚果" },
            { fruit: "香蕉", veg: "土豆", nut: "杏仁" },
            { fruit: "西瓜", veg: "豆芽", nut: "核桃" }
        ];

方法1:

var newArr = [];
         basket.forEach((item,index)=>{
             // console.log(item);
             // 初始化 二维数组
             // 预期数据结构 [[],[],[],[]]
             newArr.push([]);
             // 3. 对象遍历
             for(let key in item){
                 newArr[index].push(item[key])
             }
         })
console.log(newArr);

方法2:

var newArr = [];
        basket.forEach(item=>{
            // console.log(Object.values(item));
            // 对象转数组 之后 push 进新数组
            newArr.push(Object.values(item))
        })
console.log(newArr); 

方法3:

var newArr = basket.map(item=>{
            return Object.values(item);
        })
console.log(newArr);

8. 实现 add(1)(2)(3)

function add (...args) {
    //求和
    return args.reduce((a, b) => a + b)
}

function currying (fn) {
    let args = []
    return function temp (...newArgs) {
        if (newArgs.length) {
            args = [
                ...args,
                ...newArgs
            ]
            return temp
        } else {
            let val = fn.apply(this, args)
            args = [] //保证再次调用时清空
            return val
        }
    }
}

let addCurry = currying(add)
console.log(addCurry(1)(2)(3)(4, 5)())  //15
console.log(addCurry(1)(2)(3, 4, 5)())  //15
console.log(addCurry(1)(2, 3, 4, 5)())  //15

9. 将数组扁平化并去除其中重复数据,最终得到一个升序且不重复的数组

Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})

10. 字符串出现频率最高的字母

let str = 'qwef433eht432qax543456uhgbvf32435465'
// 将字符串转换成数组
var arr = str.split('')
let obj = {};
arr.forEach(item => {
    if (obj[item]) {
        obj[item]++
    } else {
        obj[item] = 1
    }
})
let arr1 = []
for (let key in obj) {
    //对象 转 数组对象
    let obj2 = {
        num: key,
        val: obj[key]
    }
    arr1.push(obj2)
}
arr1.sort((a, b) => {
    return b.val - a.val
})
console.log(`字符串中${arr1[0].num}出现的最多,出现了${arr1[0].val}次`);

11. 如何判断一个对象是否为数组

function isArray(arg) {
    if (typeof arg === 'object') {
        return Object.prototype.toString.call(arg) === '[object Array]';
    }
    return false;
}

12. 冒泡排序

对数组 [5,3,9,4,6] , 进行降序排列

var arr = [5,3,9,4,6];
        // 轮数
        for(var i = 0;i<arr.length-1;i++){
            // 次数
            for(var j =i+1;j<arr.length;j++){
                if(arr[i]<arr[j]){    // 如果是升序arr[i]>arr[j]
                    // 交换两个变量的值
                    [arr[i],arr[j]]=[arr[j],arr[i]]
                }
            }
        }
console.log(arr);

13. 快速排序法(递归)

随机获取10到999之间的100个整数,并且要从大到小排序,要求使用快速排序算法

function arrSort(arr) {
            // 递归的出口
            if(arr.length<=1){
                return arr;
            }
            // 取出中间数
            var index = Math.floor(arr.length / 2);
            // 需要取出中间数,并且改变原数组
            // splice 数组删除常用  从index开始,删一个 返回删除项
            var mid = arr.splice(index, 1)[0];
            // 将原数组 分左右  (左大右小)
            var left = [], right = [];
            for (var i = 0; i < arr.length; i++) {
                if(arr[i]<mid){
                    right.push(arr[i]);
                }else{
                    left.push(arr[i]);
                }
            }
            // concat方法 做数组合并 
            // 进入递归(left right)
            return arrSort(left).concat(mid,arrSort(right));
        }
console.log(arrSort(arr));

14. 浅拷贝

    var p1 = {
            name:"张三",
            age:20,
            favs:["吃饭","睡觉","钓鱼"],
            wife:{
                name:"翠花",
                age:49,
                favs:["爱马仕","迪奥","香奈儿"]
            }
        }

        var p2 = {};   // 初始化
        // 浅拷贝: 表层的一个复制
        for(var key in p1){
            p2[key] = p1[key];
        }

15. 深拷贝

    var p1 = {
            name:"张三",
            age:20,
            favs:["吃饭","睡觉","钓鱼"],
            wife:{
                name:"翠花",
                age:49,
                favs:["爱马仕","迪奥","香奈儿"]
            }
        }
    var p2 = {};   // 初始化
    // 需要两个参数  cur p1  tar p2 
        function deepCopy(cur,tar){
            for(var key in cur){
                // 涉及到枚举性问题, 只需要复制实例成员
                // key 的 实例成员的判断 (排除了原型成员里面可枚举的属性)
                if(cur.hasOwnProperty(key)){
                    // 对象的value值类型判断
                    if(typeof cur[key] == "object"){
                        // 引用数据类型
                        // [] 和 {} 的判断
                        // Array.isArray(cur[key])  用来判断是不是数组
                        tar[key]=Array.isArray(cur[key])?[]:{};
                        // 递归入口 实现深层次拷贝
                        deepCopy(cur[key],tar[key]);
                    }else{   // 出口
                        // 基本数据类型
                        // 浅拷贝
                        tar[key] = cur[key];
                    }
                }
            }
        }
        deepCopy(p1,p2);
        p2.wife.favs[0] = "好再来";
        console.log(p1,p2);

16. 不借助临时变量,进行两个整数的交换

let a = 2,
    b = 3;
    [b,a] = [a,b]
console.log(a,b)   // 3 2

17. 如何把一个字符串的大小写取反(大写变小写,小写变大写),例如'AbC' 变成 'aBc'?

let str = 'aBc';
str = str.replace(/[a-zA-Z]/g, content => {
    return content.toUpperCase() === content ? content.toLowerCase() : content.toUpperCase();
})

18. 请写出三种对象合并的方法

let arr1 = {
    a:1,
    b:2,
    c:3
};
let arr2 = {
    d:4,
    e:5,
    a:6
};

方法1: 拓展运算符,后面相同的属性覆盖前一个

let arr3={...arr1,...arr2};

//方法2: Object.assign(),后面相同的属性覆盖前一个

let arr3=Object.assign(arr1,arr2);

//方法3: Object.keys(),相同的属性只取第一个

Object.keys(arr1).forEach(key => {
    arr2[key] = arr1[key]
})