作用: call,apply,bind可以动态改变传入函数的this

使用: f.call(o,para1,para2…)

f.apply(o,[para1,para2…])

应用:

借用方法

  1. var xm = {
  2. name: '小明',
  3. food: '饺子',
  4. cook: function() {
  5. console.log("我把" + this.food + "做好了");
  6. }
  7. }
  8. var xl = {
  9. name: '小李',
  10. food: '方便面'
  11. }
  12. xm.cook();
  13. xm.cook.call(xl);
  14. xm.cook.apply(xl);

实现继承

  1. function Animal(name) {
  2. this.name = name;
  3. this.showName = function() {
  4. alert(this.name);
  5. }
  6. }
  7. function Cat(name) {
  8. Animal.apply(this, [name]);
  9. //Animal.call(this, name);
  10. }
  11. var cat = new Cat("咕咕");
  12. cat.showName();

区别

  1. call apply 第一个参数都是一样的,这个参数将代表this指向的对象
  2. call 接收的参数 需要 一个个的 枚举出来
  3. apply 接收的参数, 可以直接是一个数组,也可以是类数组对象(arguments)

手写call

  1. let obj1 = {
  2. value: 1
  3. }
  4. let obj2 = {
  5. value: 2,
  6. getValue(name, age) {
  7. return {
  8. value: this.value,
  9. name: name,
  10. age: age
  11. }
  12. }
  13. }
  14. Function.prototype.myCall = function () {
  15. const fn = Symbol('fn') //用symbole声明一个独有的属性,防止覆盖已有属性
  16. let ctx = arguments[0] || window // 如果没有this传入,默认绑定window对象
  17. ctx.fn = this // 函数赋值(改变this执行);可以再次输出this,查看效果
  18. let args = [...arguments].slice(1) // 获取传入的参数。这里为了下面方便判断,所以截去第一个参数(this),并且把剩余参数变为数组;
  19. let result = args.length > 0 ? ctx.fn(...args) : ctx.fn() // 执行当前函数
  20. delete ctx.fn // 删除我们改写的fn属性。因为不能改变原有对象,我们只是改变this,执行完就删除
  21. retun result // 返回结果
  22. }
  23. // 调用
  24. console.log('call方法改写', obj2.myCall(obj1,'小明',12))

步骤分解

语义分解: 上面函数调用call函数,内部代码就变成了这样

  1. 1. 会先判断当前是否有this,也就是是否是{}。
  2. 2. 声明一个独有的属性,方便调用
  3. 3. 改变this指向(函数赋值)
  4. 4. 根据当前传入的参数个数,来判断执行函数所带的参数
  5. 5. 删除改变的fn属性
  6. 6. 返回结果
  7. // 调用前
  8. // let obj1 = {
  9. // value: 1
  10. // }
  11. // 调用后
  12. let obj1 = {
  13. value: 1,
  14. getValue(name, age) {
  15. return {
  16. value: this.value,
  17. name: name,
  18. age: age
  19. }
  20. }
  21. }
  22. ++++++++++++++++++++++++++++
  23. let obj2 = {
  24. value: 2,
  25. getValue(name, age) {
  26. return {
  27. value: this.value,
  28. name: name,
  29. age: age
  30. }
  31. }
  32. }

代码分解

  1. 1. const fn = Symbol('fn')// Symbol 作为对象的属性名,可以保证属性不重名
  2. 2. arguments: 任意一个函数的内部,都有一个arguments对象
  3. arguments作用:获取传递来的所有实参,他是一个类数组,类数组。l
  4. 3. 类数组转化为数组的方法 [...argument] Array.from(arguments) Array.prototype.
  5. slice.call(arguments)

手写apply

  1. let obj1 = {
  2. value: 1
  3. }
  4. let obj2 = {
  5. value: 2,
  6. getValue(name, age) {
  7. return {
  8. value: this.value,
  9. name: name,
  10. age: age
  11. }
  12. }
  13. }
  14. Function.prototype.myApply = function () {
  15. const fn = Symbol('fn')
  16. let ctx = arguments[0] || window
  17. ctx.fn = this
  18. let args = [...arguments].slice(1)
  19. let result = args.length > 0 ? ctx.fn(...args) : ctx.fn()
  20. delete ctx.fn
  21. return result
  22. }
  23. // 调用
  24. console.log('call方法改写', obj2.myApplyl(obj1,'小明',12))

bind返回一个新的函数 ,所以需要重新调用一次