• JavaScript 面试题


    深拷贝

    JSON.parse(JSON.stringnify(object)) 的不足:

    • 会忽略 undefined
    • 会忽略 symbol
    • 不能序列化函数
    • 不能解决循环引用的对象

    自己实现一个深拷贝

    function deepCopy(obj) {
      let newObj
      if (typeof obj === 'object') { // 数组或对象 typeof 会返回'object'
        newObj = Array.isArray(obj) ? [] : {}
        for(let key in obj) {
          if (obj.hasOwnProperty(key)) {
            // 如果对象的属性仍然为对象/数组则递归
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
          }
        }
      } else {
        newObj = obj // 简单数据类型直接复制
      }
      return newObj
    }
    

    测试一下

    let a = {
      age: undefined,
      sex: Symbol('male'),
      jobs: function () {},
      name: 'cmk'
    }
    
    let b = JSON.parse(JSON.stringify(a))
    console.log(b) // { name: 'cmk' }
    let c = deepCopy(a)
    console.log(c) // { age: undefined, sex: Symbol(male), jobs: [Function: jobs], name: 'cmk' }
    

    数组扁平化 5 种方法

    const arr = [1, [2, 3, [4, 5]]]
    function flattern(arr) {
      return arr.reduce((preValue, currValue, currIndex, array) => {
        return preValue.concat(Array.isArray(currValue) ? flattern(currValue) : currValue)
      }, []) // []作为第一个preValue
    }
    
    // toString & split
    function flattern2(arr) {
      return arr.toString().split(',').map(item => {
        return Number(item) // split分隔后数组元素为字符串形式, 需要转换为数值形式
      })
    }
    PS:该方法及下一种方法都有一个问题,即[1, '1', 2, '2']的结果是[1, 1, 2, 2],我们改变了原数据(类型),这是不应该的
    // join & split
    function flattern3(arr) {
      return arr.join(',').split(',').map(item => { // join方法和toString方法效果一样?
        return parseInt(item)
      })
    }
    
    // concat递归
    function flattern4(arr) {
      let res = []
      arr.map(item => {
        if (Array.isArray(item)) {
          res = res.concat(flattern(item))
        } else {
          res.push(item)
        }
      })
      return res
    }
    
    // 扩展运算符
    function flattern5(arr) {
      while (arr.some(item => Array.isArray(item))) { // 如果数组元素中有数组
        arr = [].concat(...arr) // [].concat(...[1, 2, 3, [4, 5]]) 扩展运算符可以将二维数组变为一维的
      }
      return arr
    }
    

    如果只是将二维数组扁平化为一维数组的话也可以这样写

    function flattern(arr) {
      return Array.prototype.concat.apply([], arr)
    }
    

    函数柯里化

    在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
    函数柯里化的主要作用和特点就是参数复用、提前返回和延迟执行。

    简单来说,思路就是参数不够的话就存储参数并返回一个函数准备接收新的参数,参数够了的话就执行。

    function curry(fn, args1 = []) { // 默认值设为[],防止访问args1.length报错
      return fn.length === args1.length ? fn.apply(null, args1) : function (...args2) {
        return curry(fn, args1.concat(args2))
      }
    }
    
    // fn(a,b,c,d)=>fn(a)(b)(c)(d)
    // fn(a,b,c,d)=>fn(a, b)(c)(d)
    function add(a, b, c, d) {
      console.log(a + b + c + d)
    }
    
    let curryAdd = curry(add)
    curryAdd(1, 2)(3)(4) // 10
    curryAdd(1)(2)(3)(4)
    curryAdd(1, 2, 3, 4)
    

    另一种常见的问题

    /* 
        实现一个add方法,使计算结果能够满足如下预期:
        add(1)(2)(3) = 6;
        add(1, 2, 3)(4) = 10;
        add(1)(2)(3)(4)(5) = 15; 
    */
    
    function add() {
        // 第一次执行时,定义一个数组专门用来存储所有的参数
        var _args = Array.prototype.slice.call(arguments);
    
        // 在内部声明一个函数,利用闭包的特性保存 _args 并收集所有的参数值
        var _adder = function() {
            _args.push(...arguments);
            return _adder;
        };
    
        // 利用 toString 隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
        _adder.toString = function () {
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }
        return _adder;
    }
    
    add(1)(2)(3)                // 6
    add(1, 2, 3)(4)             // 10
    add(1)(2)(3)(4)(5)          // 15
    add(2, 6)(1)                // 9
    
  • 相关阅读:
    百度开发者中心BAE新建Java应用
    微信公众平台开发(三)位置信息的识别
    确定路名、标志性建筑和商场名的经度纬度
    Eclipse中Java Project转换为Java Web Project
    你应该知道的8个Java牛人
    周边信息查询
    在Java中避免空指针异常(Null Pointer Exception)
    google guava使用例子/示范(一)
    docker 相关链接
    HashMap 的数据结构
  • 原文地址:https://www.cnblogs.com/cmk1018/p/11347601.html
Copyright © 2020-2023  润新知