JavaScript面试手写题总结

110 阅读2分钟

1. 实现Bind、apply、call

call

Function.prototype.myCall = function(target,...args){
  target = target || window
  const symbolKey = Symbol()
  target[symbolKey] = this
  const res = target[symbolKey](...args) // args本身是rest参数,搭配的变量是一个数组,数组解构后就可以一个个传入函数中
  delete target[symbolKey] // 执行完借用的函数后,删除掉,留着过年吗?
  return res
}

apply

Function.prototype.myApply = function(target,args){ // 区别就是这里第二个参数直接就是个数组
  target = target || window
  const symbolKey = Symbol()
  target[symbolKey] = this
  const res = target[symbolKey](...args) // args本身是个数组,所以我们需要解构后一个个传入函数中
  delete target[symbolKey] // 执行完借用的函数后,删除掉,留着过年吗?
  return res
}

bind

Function.prototype.myBind = function (target,...outArgs) {
  target = target || {} // 处理边界条件
  const symbolKey = Symbol()
  target[symbolKey] = this
  return function (...innerArgs) { // 返回一个函数
    const res = target[symbolKey](...outArgs, ...innerArgs) // outArgs和innerArgs都是一个数组,解构后传入函数
    // delete target[symbolKey] 这里千万不能销毁绑定的函数,否则第二次调用的时候,就会出现问题。
    return res
  } 
}

2. 数组扁平化

function flatten (arr) {
    let res = [];
    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            res.push(...flatten(arr[i]));
        } else {
            res.push(arr[i]);
        }
    }
    return res;
}
  const a = [1, [2, [3, 4], [5, 6]]];
  console.log(flatten(a));  // 输出[1,2,3,4,5,6]

3.函数柯里化

function createCurry(func, args) {
  var argity = func.length;
  var args = args || [];
  
  return function () {
    var _args = [].slice.apply(arguments);
    args.push(..._args);
    
    if (args.length < argity) {
      return createCurry.call(this, func, args);
    }
    
    return func.apply(this, args);
  }
}

4.数组去重

Array.from(new Set([1, 1, 2, 2]))

5.深拷贝

function deepCopy(obj) {
    if (typeof obj === 'object') {
        var result = obj.constructor === Array ? [] : {};

        for (var i in obj) {
            result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
        }
    } else {
        var result = obj;
    }

    return result;
}

deepCopy({
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    },
    a1: undefined,
    a2: null,
    a3: 123
})

6.浅拷贝

function shallowCopy (params) {
    // 基本类型直接返回
    if (!params || typeof params !== "object") return params;
    // 根据 params 的类型判断是新建一个数组还是对象
    let newObject = Array.isArray(params) ? [] : {};
    // 遍历 params 并判断是 params 的属性才拷贝
    for (let key in params) {
        if (params.hasOwnProperty(key)) {
            newObject[key] = params[key];
        }
    }
    return newObject;
}
let params = { a: 1, b: { c: 1 } }
let newObj = shallowCopy(params)

// 拷贝对象中---基本类型老死不相往来,引用类型藕断丝连
params.a = 222
params.b.c = 666
console.log(params); // { a: 222, b: { c: 666 } }
console.log(newObj); // { a: 1, b: { c: 666 } }

7.节流

function throttle(func, delay) {
    var timer = null;
    return function () {
        if (!timer) {
            func.apply(this, arguments);
            timer = setTimeout(() => {
                timer = null;
            }, delay);
        } else {
            console.log("上一个定时器尚未完成");
        }
    }
}

8.防抖

function debounce(func, delay) {
    var timeout;
    return function() {
        clearTimeout(timeout);
        timeout = setTimeout(()=>{
            func.apply(this, arguments);
        }, delay);
    }
}

9.创建ajax

<body>
  <script>
    function ajax(url) {
      const xhr = new XMLHttpRequest();
      xhr.open("get", url, false);
      xhr.onreadystatechange = function () {
        // 异步回调函数
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            console.info("响应结果", xhr.response)
          }
        }
      }
      xhr.send(null);
    }
    ajax('https://smallpig.site/api/category/getCategory')
  </script>
</body>

10.创建一个Ajax

具体来说,AJAX 包括以下几个步骤。

1.创建 XMLHttpRequest 对象,也就是创建一个异步调用对象

2.创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、URL 及验证信息

3.设置响应 HTTP 请求状态变化的函数

4.发送 HTTP 请求

5.获取异步调用返回的数据

6.使用 JavaScript 和 DOM 实现局部刷新

function getJSON(url) {
  // 创建一个 promise 对象
  let promise = new Promise(function(resolve, reject) {
    let xhr = new XMLHttpRequest();

    // 新建一个 http 请求
    xhr.open("GET", url, true);

    // 设置状态的监听函数
    xhr.onreadystatechange = function() {
      if (this.readyState !== 4) return;

      // 当请求成功或失败时,改变 promise 的状态
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };

    // 设置错误监听函数
    xhr.onerror = function() {
      reject(new Error(this.statusText));
    };

    // 设置响应的数据类型
    xhr.responseType = "json";

    // 设置请求头信息
    xhr.setRequestHeader("Accept", "application/json");

    // 发送 http 请求
    xhr.send(null);
  });

  return promise;
}