前端面试之手写代码

240 阅读2分钟

_new 方法实现

/**
 * 思路:
 * 创建一个对象
 * 对象.__proto__ = 构造函数.prototype
 * 执行构造函数
 */
function _new(A, ...args) {
  const o = {};
  o.__proto__ = A.prototype;
  const res = A.apply(this, args);
  if(res && (typeof(res) === 'object' || typeof(res) === 'function'){
      return res;
  }
  return o;
}

apply2

Function.prototype.apply2 = function (content = window) {
  content.fn = this;
  let result;
  if (arguments[1]) {
    result = content.fn(...arguments[1]);
  } else {
    result = content.fn();
  }
  delete content.fn;
  return result;
}
;

call2 实现

Function.prototype.call2 = function (content = window) {
  content.fn = this;
  const args = [].slice(arguments, 1);
  const result = content.fn(...args);
  delete content.fn;
  return result;
};

bind

/**
 * 思路
 * 1. 绑定this
 * 2. 能接受参数
 * 3. 返回一个绑定函数
 * 4. 绑定函数能返回值
 * 5. 绑定函数能使用new
 * 6. 绑定函数new出来对象能继承原函数的属性
 */

Function.prototype.bind2 = function (context, ...args1) {
  const self = this;
  function fBound(...args2) {
    return self.apply(this instanceof fBound ? this : context, [...args1, ...args2]);
  }
  function fNOP() {}
  // 维护原型关系
  if (this.prototype) {
    fNOP.prototype = this.prototype;
  }
  // 下行的代码使fBound.prototype是fNOP的实例,因此
  // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
  fBound.prototype = new fNOP();
  return fBound;
};


const foo = {
  value: 1
}
;
function bar(name, age) {
  this.name = name;
  this.age = age;
  console.log(this.value);
}
bar.prototype.friend = 'kevin';
bar.prototype.getName = function () {
  console.log(this.name);
};
const NewBar = bar.bind(foo, 'hpy');
// NewBar();
const obj = new NewBar(20);
console.log(obj);
console.log(obj.constructor);

// NewBar.prototype.friend = 'aaa'; // 修改绑定函数原型属性不会影响原函数的原型属性
// console.log(bar.prototype.friend);
// bind 当作构造器,bind的this就失效了,所以当构造器使用,没啥意义了。

curry

const curry = (fn, ...args1) => 
args1.length < fn.length
? (...args2) => curry(fn, ...args1, ...args2) 
: fn(...args1);

instanceof

/**
 * A 为实例
 * B 为构造器
 */

function instanceof1(A, B) {
  const O = B.prototype;
  A = A.__proto__;
  while (true) {
    if (A === null) return false;
    if (A === O) return true;
    A = A.__proto__;
  }
}

function F() {
}
const newF = new F();
console.log(instanceof1(newF, F));

debounce

/**
 * 手写防抖(debounce)
 * @param fn
 * @param wait
 * @return fun
 * 思考:防抖-> 一定时间内只执行一次
 * 利用clearTimeout清除setTimeout来实现
 * 返回一个函数
 */
function debounce(fn, wait = 200) {
  let timer;
  return function (...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, wait);
  };
}

throttle

/**
 * 函数节流
 * throttle
 * @param fn
 * @param wait
 */
 function throttle(fn, wait = 200){
     let prev = new Date();
     return function(...args){
         const now = new Date();
         if(now - prev > wait){
             fn.apply(this, args);
             prev = new Date();
         }
     }
 }

add(1,2)(3,4) 无限累加

const sum = (...args) => args.reduce((total, num) => total + num, 0);

const add = (...args1) => {
    const total = sum(...args1);
    const temp = (...args2) => add(total, ...args2);
    temp.toString = () => total;
    return temp;
}

reduce实现map

Array.prototype.map1 = function(cb){
    return this.reduce((res, cur, i) => res.concat(cb(cur, i, this)), []);
}