返回

手撕JavaScript面试题解题思路

前端

在IT行业,前端开发工程师是备受追捧的人才,他们的薪酬高昂,发展前景广阔。而要成为一名优秀的前端开发工程师,除了扎实的基本功外,还需要掌握大量的知识和技巧,这些知识和技巧往往是通过面试来考察的。

在前端开发工程师的面试中,JavaScript是必考的科目之一,而JavaScript的手撕面试题更是重中之重。这些题目往往比较难,需要考生对JavaScript有深入的理解,并且能够熟练地编写代码。

为了帮助大家更好地备考前端开发工程师的面试,本文整理了高频JavaScript手撕面试题,并给出解题思路。这些题目涵盖了JavaScript的核心概念,如原生Ajax请求、Apply、Call、bind、bind与call的区别、作用域、柯里化、深拷贝、防抖与节流、事件委托、发布订阅模式等。旨在帮助开发者更好地理解JavaScript的基础知识和应用,为面试做好充分的准备。

  1. 原生Ajax请求
function ajax(url, method, data, success, error) {
  var xhr = new XMLHttpRequest();
  xhr.open(method, url, true);
  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.onload = function() {
    if (xhr.status >= 200 && xhr.status < 300) {
      success(xhr.responseText);
    } else {
      error(xhr.responseText);
    }
  };
  xhr.onerror = function() {
    error(xhr.responseText);
  };
  xhr.send(data);
}
  1. Apply
Function.prototype.apply = function(context, args) {
  context.fn = this;
  var result = context.fn(...args);
  delete context.fn;
  return result;
};
  1. Call
Function.prototype.call = function(context, ...args) {
  context.fn = this;
  var result = context.fn(...args);
  delete context.fn;
  return result;
};
  1. bind
Function.prototype.bind = function(context, ...args) {
  var fn = this;
  return function(...args2) {
    return fn.apply(context, args.concat(args2));
  };
};
  1. bind与call的区别

bind与call的区别在于,bind不立即执行函数,而只是返回一个新的函数,这个新的函数在执行时,会将this指向bind传入的第一个参数。而call则立即执行函数,并将this指向bind传入的第一个参数。

  1. 作用域

JavaScript的作用域分为全局作用域和局部作用域。全局作用域是指在脚本中定义的变量和函数,它们可以在脚本的任何地方访问。局部作用域是指在函数内部定义的变量和函数,它们只能在函数内部访问。

  1. 柯里化

柯里化是指将一个函数拆分成多个函数,每个函数都接受一个参数。这样可以使函数更加灵活,更容易复用。

function curry(fn) {
  return function(...args) {
    if (args.length >= fn.length) {
      return fn(...args);
    } else {
      return function(...args2) {
        return curry(fn)(...args, ...args2);
      };
    }
  };
}
  1. 深拷贝

深拷贝是指将一个对象的所有属性和值都复制到另一个对象中,包括嵌套的对象和数组。

function deepCopy(obj) {
  if (typeof obj !== "object" || obj === null) {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(deepCopy);
  }

  var newObj = {};
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepCopy(obj[key]);
    }
  }

  return newObj;
}
  1. 防抖与节流

防抖是指在规定时间内只执行一次函数,即使在规定时间内函数被多次调用。节流是指在规定时间内只执行一次函数,但如果在规定时间内函数被多次调用,则只执行最后一次调用。

function debounce(fn, delay) {
  var timer = null;
  return function() {
    var context = this;
    var args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  };
}

function throttle(fn, delay) {
  var lastTime = 0;
  return function() {
    var context = this;
    var args = arguments;
    var now = +new Date();
    if (now - lastTime > delay) {
      fn.apply(context, args);
      lastTime = now;