Skip to content
字数
1241 字
阅读时间
7 分钟

手写 forEach

javascript
// 注意forEach存在一种,forEach(callbackFn, thisArg) 的方式为callbackFn绑定this
Array.prototype.forEach(callback, context) {
    if (this === null) {
        throw new TypeError('this is null or not undefined')
    }
    if (typeof callback !== 'function') {
        throw new TypeError(callback + " is not a function");    }
    const length = this.length;
    const that = this;
    let i = 0;
    while (i < length) {
        callback.call(context, that[i], i, that);
        i++;
    }
}

手写 new

es6 中的 class 含义:

js
class Point {
  // ...
}

typeof Point // "function"
Point === Point.prototype.constructor // true
javascript
objectFactory(构造函数, 初始化参数);
/**
 * 1. 创建一个新对象
 * 2. 将构造函数的prototype指向constructor
 * 3. 将实例的this指向构造函数
 * 4. 判断返回结果
 **/
js
function objectFactory() {
  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);
  console.log(newObject) // object, 是hlper {} 空对象
  // 将 this 指向新建对象,并执行函数
  result = constructor.apply(newObject, arguments);
  console.log(result)  // undefined
  // 判断返回对象,如果constructor的返回值是函数或者object,则返回返回值
  let flag = result && (typeof result === "object" || typeof result === "function");
  // 判断返回结果
  return flag ? result : newObject;
}
// 使用方法
function helper(name) {
    this.name = name
    // return function () {
    //     console.log('jjj')
    // }
    return {
        name: 'jie'
    }
}
let a = objectFactory(helper, 'jiechen');
console.log(a)

手写 call 和 apply

使用调用者提供的 this 值和参数调用该函数。若该方法没有返回值,则返回 undefined

javascript
Function.prototype.myCall = function (thisArg) {
    if (typeof this !== 'function') {
        throw new TypeError("type error");
    }
    let args = [...arguments].slice(1);
    thisArg = thisArg || window;
    let result = null;
    
    // 将调用的函数绑定到对象的属性上
    thisArg.fn = this;
    result = thisArg.fn(...args);

    if (arguments[1]) {
        result = thisArg.fn(arguments[1]);
    } else {
        result = thisArg.fn();
    }

    delete thisArg.fn;
    return result;
}

let args = [...arguments].slice(1),fn = this

return function Fn() {
  return fn.apply(
    this instanceof Fn ? this : thisArg,
    // 实现函数柯里化,将使用多个参数的一个函数转为使用一个参数的函数
    args.concat(...arguments)
  )
}

promise

Promise 对象 -- JavaScript 标准参考教程(alpha)

简单介绍

所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
例如以下一个 promise 的例子:

javascript
new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('Hello,我是Hy')
        },1000)
 }).then((res)=>{
     console.log(res);//res这个参数就是resolve 调用后传的data,既Hello,我是Hy
 },(req)=>{
     console.log(req);
 })
// 一秒钟后打印  Hello,我是Hy

可以看出一个 promise 的构造函数包含两个方法 resolve、reject,同时根据 promise+ 规范可知 promise 包含三个状态:

pending: 初始状态,既不是成功,也不是失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。
那么我们可以可以根据这三种不同状态去实现 resolve、reject,以及实现 then 方法,那么一个简单的 promise 雏形就出来了。下面来实现它:

javascript
// 手写promise

const PENDING = "pending"
const RESOLVED = "resolved"
const REJECTED = "rejected"

function MyPromise (fn) {
  let self = this

  this.state = PENDING
  this.value = null

  this.resolveCallbacks = []
  this.rejecteCallbacks = []

  function resolve (value) {
    if (value instanceof MyPromise) {
      return value.then(resolve, reject);
    }
    if (self.state === PENDING) {
      self.state = RESOLVED
      self.value = value;

      while (self.resolveCallbacks.length) {
        self.resolveCallbacks.shift()(self.value)
      }
    }
  }

  function reject (value) {
    if (self.state === PENDING) {
      self.state = REJECTED
      self.value = value

      while (self.rejecteCallbacks.length) {
        self.rejecteCallbacks.shift()(self.value)
      }
    }
  }

  try {
    fn(resolve, reject)
  } catch (e) {
    reject(e)
  }

}

MyPromise.prototype.then = function (onResolved = data => data, onRejcted) {
  // 保存前一个promise的this
  let self = this
  let promise = new Promise((resolve, reject) => {
		// 转换为 异步执行,用来获取 新的 promise
      let resolvedHandler = setTimeout(() => {
        try {
          let res = onResolved(self.value)
          // 判断返回值是 promise 还是 普通返回值
          resolvePromise(promise, res, resolve, reject)
        } catch (e) {
          reject(e)
        }
      }, 0)
      let rejectedHandler = setTimeout(() => {
        try {
          let res = onRejected(self.value)
          resolvePromise(promise, res, resolve, reject)
        } catch (e) {
          reject(e)
        }
      }, 0)

      let peddingHandler = () => {
      // 将回调函数存入数组中等待被执行
        self.resolveCallbacks.push(() => {
          setTimeout(() => {
            try {
              let res = onResolved(self.value)
              resolvePromise(promise, res, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        }),
        self.rejecteCallbacks.push(() => {
          setTimeout(() => {
            try {
              let res = onRejected(self.value)
              resolvePromise(promise, res, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }

      // 判断返回值是 promise 还是 普通返回值
      function resolvePromise(promise, res, resolve, reject) {
		// 循环调用报错
		if (promise === res) {
		  return reject(
		    throw new TypeError('Chaining cycle detected for promise #<Promise>')
		  )
		}
        if (res instanceof MyPromise) {
          res.then(resolve, reject)
        } else {
          resolve(res)
        }
      }

      switch (self.state) {
        case PEDING:
          peddingHandler();
          break;
        case RESOLVED:
          resolvedHandler()
          break;
        case REJECTED:
          rejectedHandler()
          break
      }
  })
  return promise
}

function promiseAll(iterable) {
  let counter = 0;
  let result = [];
  return new MyPromise((resolve, reject) => {
    function addData(key, value) {
      counter++;
      result[key] = value;
      counter === iterable.length && resolve(result)
    }
    iterable.forEach((item, index) => {
      item instanceof MyPromise
        ? item.then(data => addData(index, data),
                    err => reject(err)
          )
        : addData(index, item)
    })
  })
}

sleep 函数

异步像同步一样执行,需要异步返回结果之后,再往下依据结果继续执行

javascript
// sleep函数
function sleepFun(time) {
  return new Promise(resolve => setTimeout(resolve, time))
}

async function wait(time) {
  console.time('time');
  await sleepFun(time);
  fun();
}

wait(3000); // time: 3001.204833984375ms

instanceof

javascript
function myInstanceOf (left, right) {
    if (typeof left !== 'object' || left === null || typeof right !== 'function') {
        return false;
      };
    let proto = Obejct.getPrototypeof(left),
        prototype = right.prototype;

    while (true) {
        if (!proto) return false;
        if (prototype === proto) return true;
        proto = Obejct.getPrototypeof(proto);
    }
}

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写