JS之call、apply、bind(暂缓...)

147 阅读1分钟

call

改变this指向,带参数调用一个函数。

所以要实现:

  • call改变this的指向,指向到第一个参数
  • 函数要执行
  • 可以传递多个参数
  • 参数可以为null
  • 要有返回值

模拟实现

  Function.prototype.call2 = function(context) {
        //当第一个参数是null时,就会将this指向window
        context = context || window;
        //把函数绑到指向的对象上去
        context.fn = this;
        let args = [];
        //制造一个arguments[1],arguments[2]这样的数组
        for (let i = 1, len = arguments.length; i < len; i++) {
          args.push('arguments[' + i + ']');
        }
        //使用eval,并把arguments传入函数去执行
        let result = eval('context.fn(' + args + ')');
        //把方法从指向的对象上删除
        delete context.fn;
        //返回值
        return result;
      };
      var value =1
      var foo = {
        value: 1
      };

      console.log(bar.call2(null));
      function bar(name, age) {
        return {
          value: this.value,
          name,
          age
        };
      }

      console.log(bar.call2(foo, 'will', 18));

apply

同样是改变this指向,但是后面参数是数组形式

模拟实现

Function.prototype.apply2 = function(context, arr) {
        var context = Object(context) || window;
        context.fn = this;

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

        delete context.fn;
        return result;
      };

bind

bind()会创建一个新函数。当新函数被调用时,bind的第一个参数作为运行时的this,之后的一序列参数会做为它的参数。

var foo = {
    value: 1
};

function bar(name, age) {
    console.log(this.value);
    console.log(name);
    console.log(age);

}

var bindFoo = bar.bind(foo, 'daisy');
bindFoo('18');
// 1
// daisy
// 18

函数需要传 name 和 age 两个参数,竟然还可以在 bind 的时候,只传一个 name,在执行返回的函数的时候,再传另一个参数 age!