手写js方法的源码

Posted by Xiaosa's Blog on March 15, 2020

bind

基础版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(Function.prototype.bind === undefined){
    console.log('您的浏览器不支持bind方法! 开始使用手写bind功能!');
    Function.prototype.bind = function(obj){
        var arg1 = [].slice.call(arguments,1);  // 解释一下骚操作,用 arg1 保留了当函数调用bind方法时候传入的参数,因为arguments是类数组对象,我们借用了数组的slice方法
        var fun = this; // fun —> bind调用者(也就是某个函数)
        return function(){
            fun.apply(obj,arg1.concat([].slice.call(arguments,1)));
            //  这里返回了一个闭包函数, 里面可以使用 obj , arg1 , fun 这些变量,配合起来实现了bind
        }
}
}else{
    console.log('您的浏览器支持bind方法!')
}

健壮版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis || window,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

promise

最简单版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Promise(excutor) {
  const self = this
  self.onResolvedCallback = []
  function resolve(value) {
    setTimeout(() => {
      self.data = value
      self.onResolvedCallback.forEach(callback => callback(value))
    })
  }
  excutor(resolve.bind(self))
}
Promise.prototype.then = function(onResolved) {
  const self = this
  return new Promise(resolve => {
    self.onResolvedCallback.push(function() {
      const result = onResolved(self.data)
      if (result instanceof Promise) {
        result.then(resolve)
      } else {
        resolve(result)
      }
    })
  })
}