【第二章】this、call和apply

this

指向一个对象。具体指向哪一个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

执行上下文:

JavaScript引擎在JavaScript代码正式执行之前会先创建执行环境,在执行环境中作预处理工作

  • 工作内容:
    1.创建空对象
    2.该空对象用于收集变量、函数,函数的参数
    3.创建作用域链
    4.确定this的指向

  • 执行上下文栈:
    1.在全局代码执行之前,JavaScript引擎就会创建一个栈来存储管理所有的执行上下文对象
    2.在全局执行上下文确定后,将其添加到栈中(压栈)
    3.在函数执行上下文创建后,将其添加到栈中(压栈)
    4.在当前函数执行完后,将栈顶的对象移除(出栈)
    5.当所有的代码执行完后,栈中只剩下window

  • this指向
    1.作为对象的方法调用 指向对象
    2.作为普通函数调用 指向全局对象(window)
    3.构造函数调用 指向实例对象
    4.Function.prototype.call或Function.prototype.apply调用 指向第一个参数对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    //1.作为对象的方法调用
    var obj = {
    a : 1,
    getA : function(){
    console.log( this === obj ) //true
    console.log( this.a ) // 1
    }
    }

    //2.作为普通函数调用
    window.name = 'globalName'
    var obj = {
    name : 'localName',
    getName : function(){
    console.log(this.name)
    }
    }
    var getName = obj.getName
    getName() //globalName
    obj.getName() //localName

    //3.构造函数调用
    var Obj = function(){
    this.name = 'doreen'
    this.age = 11
    }
    var obj = new Obj()
    obj.name = 'sherry'
    console.log(obj) //sherry

    //4.Function.prototype.call或Function.prototype.apply调用
    var obj = {
    name: 'doreen',
    getName: function(){
    return this.name
    }
    }

    var obj2 = {
    name: 'sherry'
    }
    console.log(obj.getName()) //doreen
    console.log(obj.getName.call(obj2)) //sherry

call和apply

  • call和apply的区别

    call多个参数 .call(对象,…)
    apply是两个参数 .apply(对象,数组)

1
2
3
4
5
6
var func = function(a,b,c){
console.log([a,b,c])
}

func.call(null,1,2,3) //[1,2,3]
func.apply(null,[1,2,3]) //[1,2,3]
  • call和apply的用途

    1. 改变this指向

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      var obj1 = {
      name: 'doreen'
      }
      var obj2 = {
      name: 'sherry'
      }
      var window.name = 'winow'
      var getName = function(){
      console.log(this.name)
      }

      getName() //window
      getName.call(obj1) //doreen
      getName.call(obj2) //sherry
    2. Function.prototype.bind

      1
      2
      3
      4
      5
      6
      7
      // 实现方法
      Function.prototype.bind = function(context){
      var obj = this
      return function(){
      return obj.apply(context,arguments)
      }
      }

      延迟执行,call和apply是改变this之后直接执行函数,而bind是返回一个函数 需要在调用才能执行

    3. 借用其他对象的方法

    • 场景一 “ 借用构造函数 ” 实现继承

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      var A = function(name){
      this.name = name
      }
      var B = function(){
      A.apply(this,arguments)
      }
      B.prototype.getName = function(){
      console.log(this.name)
      }
      var b = new B('doreen')
      b.getName() //doreen
    • 场景二 处理 “ 类数组对象 ”

      函数的参数列表 arguments 是一个类数组对象,虽然它也有“下标”,但它并非真正的数组,所以也不能像数组一样,进行排序操作或者往集合里添加一个新的元素。这种情况下,我们常常会借用 Array.prototype 对象上的方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      (function(){
      Array.prototype.push.call(arguments,3)
      console.log(arguments) //[1,2,3]
      })(1,2)

      /*数组的特性
      1.对象本身要可以存取属性
      2.对象的length属性可读写
      */

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2019-2023 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信