返回

深入浅出前端基础笔试题与解答,助你面试从容应对

前端

在前端开发中征服笔试:剖析基础概念和常见面试题

引言

对于有抱负的前端开发人员来说,笔试是求职过程中不可避免的一步。这些笔试旨在评估候选人的基础知识和对前端开发关键概念的理解。本文将深入探讨一系列常见前端笔试题,并提供详细的解答,帮助你为面试做好充分的准备。

1. bind、apply 和 call 的实现

bind

bind 方法将一个函数的 this 上下文绑定到另一个对象上,并返回一个新的函数。

代码示例:

Function.prototype.myBind = function(context, ...args) {
  if (typeof this !== "function") {
    throw new TypeError("Error");
  }
  const fn = this;
  return function(...rest) {
    return fn.apply(context, args.concat(rest));
  };
};

apply

apply 方法立即执行一个函数,并将其 this 上下文绑定到另一个对象上。

代码示例:

Function.prototype.myApply = function(context, args) {
  if (typeof this !== "function") {
    throw new TypeError("Error");
  }
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};

call

call 方法与 apply 类似,但参数列表以逗号分隔传入。

代码示例:

Function.prototype.myCall = function(context, ...args) {
  if (typeof this !== "function") {
    throw new TypeError("Error");
  }
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};

2. 防抖和节流函数的实现

防抖

防抖函数在连续触发时,只执行最后一次触发。

代码示例:

function debounce(fn, wait) {
  let timer;
  return function(...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
      timer = null;
    }, wait);
  };
}

节流

节流函数在指定时间间隔内,只执行第一次触发。

代码示例:

function throttle(fn, wait) {
  let last = 0;
  return function(...args) {
    const now = +new Date();
    if (now - last >= wait) {
      fn.apply(this, args);
      last = now;
    }
  };
}

3. Promise 的实现

Promise

Promise 对象表示异步操作的最终完成或失败及其结果。

代码示例:

class MyPromise {
  constructor(executor) {
    this.status = "pending";
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = value => {
      if (this.status === "pending") {
        this.status = "fulfilled";
        this.value = value;
        this.onFulfilledCallbacks.forEach(cb => cb(this.value));
      }
    };
    const reject = reason => {
      if (this.status === "pending") {
        this.status = "rejected";
        this.reason = reason;
        this.onRejectedCallbacks.forEach(cb => cb(this.reason));
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.status === "fulfilled") {
        try {
          const value = onFulfilled(this.value);
          resolve(value);
        } catch (err) {
          reject(err);
        }
      } else if (this.status === "rejected") {
        try {
          const reason = onRejected(this.reason);
          resolve(reason);
        } catch (err) {
          reject(err);
        }
      } else {
        this.onFulfilledCallbacks.push(() => {
          try {
            const value = onFulfilled(this.value);
            resolve(value);
          } catch (err) {
            reject(err);
          }
        });
        this.onRejectedCallbacks.push(() => {
          try {
            const reason = onRejected(this.reason);
            resolve(reason);
          } catch (err) {
            reject(err);
          }
        });
      }
    });
  }
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
  finally(onFinally) {
    return this.then(
      value => MyPromise.resolve(onFinally()).then(() => value),
      reason => MyPromise.resolve(onFinally()).then(() => { throw reason; })
    );
  }
  static resolve(value) {
    return new MyPromise(resolve => resolve(value));
  }
  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason));
  }
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      const results = [];
      let count = 0;
      promises.forEach((promise, index) => {
        promise.then(value => {
          results[index] = value;
          count++;
          if (count === promises.length) {
            resolve(results);
          }
        }).catch(reason => reject(reason));
      });
    });
  }
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(value => resolve(value)).catch(reason => reject(reason));
      });
    });
  }
}

4. new 的实现

new

new 运算符创建一个新对象,并将其原型指向构造函数的原型。

代码示例:

function myNew(fn, ...args) {
  const obj = {};
  obj.__proto__ = fn.prototype;
  const result = fn.apply(obj, args);
  return result instanceof Object ? result : obj;
}

5. instanceof 的实现

instanceof

instanceof 运算符判断一个对象是否属于某个类的实例。

代码示例:

function myInstanceof(obj, fn) {
  let proto = obj.__proto__;
  while (proto) {
    if (proto === fn.prototype) {
      return true;
    }
    proto = proto.__proto__;
  }
  return false;
}

6. reduce 的实现

reduce

reduce 方法将数组中的所有元素按序累积成一个值。

代码示例:

Array.prototype.myReduce = function(fn, initialValue) {
  let prev = initialValue ? initialValue : this[0];
  for (let i = initialValue ? 0 : 1; i < this.length; i++) {
    prev = fn(prev, this[i], i, this);
  }
  return prev;
};

7. eventbus 的实现

eventbus

eventbus 是一种事件发布-订阅模式,用于解耦组件之间的通信。

代码示例:

class EventBus {
  constructor() {
    this.events = {};
  }
  on(event, cb) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(cb);
  }
  emit(event, ...args) {
    if (!this.events[event]) {
      return;
    }
    this.events[event].forEach(cb => cb(...args));
  }
  off(event, cb) {
    if (!this.events[event]) {
      return;
    }
    const index = this.events[event].indexOf(cb);
    if (index > -1) {
      this.events[event].splice(index, 1);
    }
  }
}

8. stringify 的实现

stringify

stringify 方法将一个对象或数组转换为 JSON 字符串。

代码示例:

function myString