模拟call apply

1. call

call用于指定函数调用时候上下文对象this,比如

var a = 9;
const obj = {
  a: 2,
  show: function() {
    console.info(this.a);
  }
};

obj.show(); //2

const other = {
  a: 99
};

obj.show.call(other); //99

利用对象直接调用其函数的时候,该函数的this指向该对象,

Function.prototype.call2 = function(context, ...args) {
  context.prop = this; //将 call2的调用者 object.show 赋值给给上下文对象
  context.prop(...args); // 通过上下文对象调用被call的函数
  delete context.prop; // 不能改变context对象,所以调用完 要删除额外属性
};

obj.show(78); //2
obj.show.call2(other, 34); //99

但是这种写法扩展操作符是ES6的,所以可以改进,prop属性可能跟context已有的属性冲突,所以可以用symbol去改进

2. apply

apply 的第二个参数是数组或者类数组

var a = 9;
const obj = {
  a: 2,
  show: function(age, name, sex) {
    console.info(this.a, age, name, sex);
  }
};

obj.show(34, 'geek', 'male'); //2

const other = {
  a: 99
};

obj.show.call(other, 25, 'bill', 'jin'); //99
obj.show.apply(other, [25, 'bill', 'jin']); //99

上面的测试得到如下的结果

2 34 'geek' 'male'
99 25 'bill' 'jin'
99 25 'bill' 'jin'
说明在模拟apply的时候需要将apply的第二个参数展开给调用apply的函数

Function.prototype.apply2 = function(context, args) {
  context.prop = this;
  context.prop(...args);// 需要展开
  delete context.prop;
};


obj.show.apply2(other, [9, 8, 7]);

猜你喜欢

转载自blog.csdn.net/weixin_33912453/article/details/90846796