JavaScript 高频手写代码

283 阅读1分钟

实现 REDUCE

Array.prototype.reduce = function (callback, intialVal) { 
  var self = this,
      i = 0,
      len = self.length;
      console.log(Object.prototype.toString.call(self))
  if( !(self instanceof Array)) throw new TypeError(self+".reduce is not a function");

  if( !(/^(function)$/.test(typeof callback)) ) throw new TypeError("callback must be an function");

  // 没有初始值
  if(typeof intialVal === undefined) {
      i = 1;
      intialVal = self[0];
  }
  // 每次循环都去执行一次回调函数
  for(; i<len; i++) {
      intialVal = callback(intialVal, self[i], i);
  }
  return intialVal;
}

实现 CALL

Function.prototype.call = function call(context, ...params) {
  let self = this,
      result = null,
      key = Symbol('KEY');

      context == null ? context = window : null;
      !/^(object|function)$/.test(typeof context)? Object(context) : null;
      context[key] = self;
      result = context[key](...params);
      delete context[key];
      return result;
}

实现 APPLY

Function.prototype.apply = function call(context, params) {
      let self = this,
        result = null,
        key = Symbol('KEY'),
        args = [];

      context == null ? context = window : null;

      !/^(object|function)$/.test(typeof context) ? Object(context) : null;

      if (Object.prototype.toString.call(params) !== '[object Array]' && typeof params !== 'undefined') throw new TypeError('CreateListFromArrayLike called on non-object');

      context[key] = self;

      if (!params) {
        result = context[key]();
      } else {
        // result = context[key](...params);
        for (var i = 0, len = params.length; i < len; i++) {
          args.push('params[' + i + ']');
        }
        result = eval('context[key](' + args + ')')
      }

      delete context[key];
      return result;
    }

实现 BIND

Function.prototype.bind = function bind(context) {
  var params = [].slice.call(arguments, 1),// 截取除第一个参数之外的参数
      self = this;
      
  return function proxy() {
      var outerArgs = [].slice.call(arguments).concat(params);
      return self.apply(context, outerArgs);
  }
}

实现 NEW

function _new(Ctor) { 
  var reg = /^(object|function)$/i,
        params,
        obj,
        result;
  if( typeof Ctor !== 'function' || 
      !reg.test(typeof Ctor.prototype)) throw new TypeError('Ctor is not a constructor')

  var params = [].slice.call(arguments, 1),
      obj = Object.create(Ctor.prototype),
      result = null;

    result = Ctor.call(obj, params);

  if(reg.test(typeof result)) return result;

  return obj;
}

实现防抖

function debounce(func, wait, immediate) { 
  if(typeof func !== 'function') throw new TypeError('func must be an function');
  只有一个, 那么wait赋值默认值 500
  if(typeof wait === 'undefined') wait = 500;
  if(typeof wait === 'boolean') {
    immediate = wait;
    wait = 1500; // 默认值
  };
  if(typeof immediate !== 'boolean') immediate = false;

  let timer = null;
  return function proxy(...args) {
    let self = this,
        now = immediate && !timer;
     timer = setTimeout(()=>{
      timer = null;
      !immediate?func.call(self, ...args):null;
    }, wait);

    now?func.call(self, ...args) : null;
  };
 };

实现节流

function throttle(func, wait) {
  if(typeof func !== 'function') throw new TypeError('func must be an function');
  if(typeof wait === 'undefined') wait = 500;

  let timer = null,
      previous = 0; // 记录上一次操作的时间

  return function proxy(...param) { 
    let self = this,
        now = new Date(),
        remaining = wait - ( now - previous ); 
        if(remaining<=0) {
          clearTimeout(timer);
          timer = null;
          previous = now;
          func.call(self, ...param);
        } else if(!timer){
          timer = setTimeout(()=>{
               timer = null;
          
                clearTimeout(timer);
                func.call(self, ...param);
                previous = new Date();
          }, remaining);
        }
   };
};

实现数组/对象的浅拷贝

  • 数组的浅拷贝
let copyArr = [...arr];
let copyArr = arr.concat();
let copyArr = arr.slice();
  • 对象的浅拷贝
let copyObj = {...obj}
let copyObj = Object.assign({}, obj1)

以上两种方案都包含了 Symbol 属性的处理

for in 循环,不支持 Symbol 属性