ArthurWangCN / notepad

reading notepad
0 stars 2 forks source link

手写篇:API #13

Open ArthurWangCN opened 2 years ago

ArthurWangCN commented 2 years ago

手写实现sleep

方法一:使用 promise 配合await的异步方法来实现 sleep

(async () => {
  console.log('start');
  await sleep(3000)
  console.log('end');

  function sleep(timer) {
    return new Promise(res => {
      setTimeout(() => {
        res()
      }, timer);
    })
  }
})();

方法二:完全堵塞进程来达到sleep

(async () => {
  console.log('start');
  await sleep(3000)
  console.log('end');

  function sleep(delay) {
    let t = Date.now();
    while (Date.now() - t <= delay) {
      continue;
    }
  };
})()
ArthurWangCN commented 2 years ago

手写new操作符

new操作符的执行过程: (1)首先创建了一个新的空对象 (2)设置原型,将对象的原型设置为函数的 prototype 对象。 (3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性) (4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

代码:

function myNew() {
  let newObject = null;
  let constructor = Array.prototype.shift.call(arguments);
  let result = null;
  // 判断参数是否是一个函数
  if (typeof constructor !== "function") {
    console.error("type error");
    return;
  }
  // 新建一个空对象,对象的原型为构造函数的 prototype 对象
  newObject = Object.create(constructor.prototype);
  // 将 this 指向新建对象,并执行函数
  result = constructor.apply(newObject, arguments);
  // 判断返回对象
  let flag = result && (typeof result === "object" || typeof result === "function");
  // 判断返回结果
  return flag ? result : newObject;
}

// 使用方法
myNew(构造函数, 初始化参数);
ArthurWangCN commented 2 years ago

深拷贝方案

(1)JSON.stringify()

局限性:拷贝的对象中如果有函数,undefined,symbol,当使用过JSON.stringify()进行处理之后,都会消失。

(2)函数库lodash的_.cloneDeep方法

(3)手写实现深拷贝函数

// 深拷贝的实现
function deepCopy(object) {
  if (!object || typeof object !== "object") return;

  let newObject = Array.isArray(object) ? [] : {};

  for (let key in object) {
    if (object.hasOwnProperty(key)) {
      newObject[key] =
        typeof object[key] === "object" ? deepCopy(object[key]) : object[key];
    }
  }

  return newObject;
}
ArthurWangCN commented 2 years ago

实现数组的flat方法

function _flat(arr, depth) {
  if(!Array.isArray(arr) || depth <= 0) {
    return arr;
  }
  return arr.reduce((prev, cur) => {
    if (Array.isArray(cur)) {
      return prev.concat(_flat(cur, depth - 1))
    } else {
      return prev.concat(cur);
    }
  }, []);
}
ArthurWangCN commented 2 years ago

实现数组的push方法

let arr = [];
Array.prototype.push = function() {
    for( let i = 0 ; i < arguments.length ; i++){
        this[this.length] = arguments[i] ;
    }
    return this.length;
}
ArthurWangCN commented 2 years ago

实现数组的filter方法

Array.prototype._filter = function(fn) {
    if (typeof fn !== "function") {
        throw Error('参数必须是一个函数');
    }
    const res = [];
    for (let i = 0, len = this.length; i < len; i++) {
        fn(this[i]) && res.push(this[i]);
    }
    return res;
}
ArthurWangCN commented 2 years ago

实现数组的map方法

Array.prototype._map = function(fn) {
   if (typeof fn !== "function") {
        throw Error('参数必须是一个函数');
    }
    const res = [];
    for (let i = 0, len = this.length; i < len; i++) {
        res.push(fn(this[i]));
    }
    return res;
}
ArthurWangCN commented 2 years ago

实现字符串的repeat方法

function repeat(s, n) {
    return (new Array(n + 1)).join(s);
}
ArthurWangCN commented 2 years ago

手写实现call

Function.prototype.myCall = function(context) {
  // 判断调用对象
  if (typeof this !== "function") {
    console.error("type error");
  }
  // 获取参数
  let args = [...arguments].slice(1),
    result = null;
  // 判断 context 是否传入,如果未传入则设置为 window
  context = context || window;
  // 将调用函数设为对象的方法
  context.fn = this;
  // 调用函数
  result = context.fn(...args);
  // 将属性删除
  delete context.fn;
  return result;
};
ArthurWangCN commented 2 years ago

手写实现apply

Function.prototype.myApply = function(context) {
  // 判断调用对象是否为函数
  if (typeof this !== "function") {
    throw new TypeError("Error");
  }
  let result = null;
  // 判断 context 是否存在,如果未传入则为 window
  context = context || window;
  // 将函数设为对象的方法
  context.fn = this;
  // 调用方法
  if (arguments[1]) {
    result = context.fn(...arguments[1]);
  } else {
    result = context.fn();
  }
  // 将属性删除
  delete context.fn;
  return result;
};
ArthurWangCN commented 2 years ago

手写bind

Function.prototype.myBind = function(context) {
  // 判断调用对象是否为函数
  if (typeof this !== "function") {
    throw new TypeError("Error");
  }
  // 获取参数
  var args = [...arguments].slice(1),
    fn = this;
  return function Fn() {
    // 根据调用方式,传入不同绑定值
    return fn.apply(
      this instanceof Fn ? this : context,
      args.concat(...arguments)
    );
  };
};

注意:

  1. 函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
  2. args.concat(...arguments) 拼接后面传的参数。