三者区别:

  • (都是es5的api),apply与call都是 执行函数的同时,改变函数的this指向。区别在于它们的参数方式不同: ```javascript //案例1 第一个参数是一致的 const obj = { a:()=>{console.log(this)}, //绑定到了外部环境 即window b:function(){console.log(this)} //取决于执行环境 } obj.b() // 打印 obj 对象 <=> 由obj调用 const calledObj = {a:1} obj.b.call(calledObj); // 第一个参数即改变后的this指向 <=> 打印calledObj obj.b.apply(window); // 同上 <=> 打印window

// 案例2 后面参数是不同形式的 function fo(a,b,c){ console.log(this) console.log(a,b,c) } fo(1,2,3); //打印window 1,2,3 fo.call(calledObj,1,2,3); 打印calledObj,1,2,3 fo.apply(calledObj,[1,2,3]);

  1. - bind不会改变原函数的this指向,但会返回一个新的函数,新的函数绑定了this指向;
  2. ```javascript
  3. // 案例
  4. function fo2(prop){
  5. console.log(this);
  6. console.log(prop);
  7. }
  8. const calledObj2 = {a:1}
  9. fo2(2) ; // 打印window , 2;
  10. const newFo = fo2.bind(calledObj2); // 返回了一个新的函数哟
  11. newFo(3); // 打印calledObj2, 3;

call,apply,bind的封装

  1. // 封装一个myCall
  2. Function.prototype.myCall = function(...args){
  3. const [context,...others] = args;
  4. context.fn = this; // 这个this指向Function的实例对象,也就是那个函数
  5. const result = context.fn(...others);
  6. delete context.fn; // 别忘记干掉这个属性
  7. console.log(context);
  8. return result;
  9. }
  10. // 试一试
  11. function fo(a,b,c){
  12. console.log(this,a,b,c);
  13. }
  14. const calledObj = {a:1}
  15. fo.myCall(calledObj,1,2,3);
  16. // 同理,封装一个myApply
  17. Function.prototype.myApply = function(context,args){
  18. context.fn = this;
  19. const result = context.fn(...args);
  20. delete context.fn; // 别忘记干掉这个属性
  21. return result;
  22. }
  23. // 试一试
  24. fo.myApply(calledObj,[1,2,3])
  25. // 那么再封装一个myBind,暂不考虑new的场景
  26. Function.prototype.myBind = function(context=window){
  27. const _this = this;
  28. const newFn = function(...args){
  29. return _this.apply(context,args);
  30. };
  31. return newFn;
  32. }
  33. // 试一试
  34. const newFo = fo.myBind(calledObj);
  35. newFo(1,2,3);