apply

概念

概念:方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。 语法:function.call(thisArg, [argsArray]) 参数: thisArg:可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。 返回值:使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。

原理

分析: 他们改变的this指向的原理:

  • 其实就是通过在 某个对象上添加这样一个方法,
  • 然后拿到参数,
  • 再去调用这个对象的这个方法(符合this指向调用者。) 。
  • 得到结果后,再在这个对象上删去这个属性方法。
  • 最后返回结果。(想一想,其实很简单是不是)

    实现

    call
  • 首先 context 为可选参数,

  • 如果不传的话默认上下文为 window 接下来给 context 创建一个 fn 属性,并将值设置为需要调用的函数
  • 因为 apply 传参是数组传参,所以取得数组,将其剥离为顺序参数进行函数调用
  • 然后调用函数并将对象上的函数删除
  1. function Animal(name,color){
  2. this.name = name||'动物';
  3. this.color = color||'颜色';
  4. this.say=function(){
  5. console.log(`Animal:${this.name},${this.color}`)
  6. }
  7. }
  8. function Dog(name,color){
  9. Animal.apply(this,[name,color]);
  10. this.say=function(){
  11. console.log(`Dog:${this.name},${this.color}`)
  12. }
  13. }
  14. let newDog = new Dog('小狗','棕色');
  15. let newDog2 = new Dog();
  16. newDog.say()
  17. newDog2.say();
  18. Function.prototype.myApply=function(context){
  19. // 判断调用者是否为函数
  20. if (typeof this !== 'function') {
  21. throw new TypeError('Error')
  22. }
  23. //如果不传默认window
  24. context = context || window;
  25. // 新增 fn 属性,将值设置为需要调用的函数
  26. context.fn = this;
  27. // 返回执行结果
  28. let result;
  29. //判断是否有参数传入
  30. if(arguments[1]){
  31. result = context.fn(...arguments[1])
  32. }else{
  33. result = context.fn();
  34. }
  35. // 删除函数
  36. delete context.fn;
  37. return result
  38. }
  39. function Cat(name,color){
  40. Animal.myApply(this,[name,color]);
  41. this.say=function(){
  42. console.log(`Cat:${this.name},${this.color}`)
  43. }
  44. }
  45. let newCat = new Cat('小猫','棕色');
  46. let newCat2 = new Cat();
  47. newCat.say()
  48. newCat2.say();

image.png

示例

  1. 用 apply 将数组各项添加到另一个数组
  2. 使用apply和内置函数
  3. 使用apply来链接构造器