JavaScript中this的指向

        JavaScript跟别的语言大相径庭,JavaScript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

除去不常用的with和eval的情况,具体到实际应用中,this的指向大致可以分为以下4种:

  • 作为对象的方法调用。

  • 作为普通函数调用。

  • 构造器调用。

  • Function.prototype.call 或 Function.prototype.apply调用。

  1. 作为对象的方法调用

        当函数作为对象的方法被调用时,this指向该对象,代码如下:

var obj = {
  a: 1,
  getA: function() {
    console.log(this === obj) // true
    console.log(this.a) // 1
  }
}

obj.getA()

2.  作为普通函数调用

当函数不作为对象的属性被调用时,也就是我们常说的普通函数方式,此时的this总是指向全局对象。在浏览器的JavaScript里,这里的全局对象时window对象。代码如下:

window.name = 'globalName'
var getName = function() {
  return this.name
}
console.log(getName())// globalName
window.name = 'globalName'
var myObj = {
  name: 'summer',
  getName: function() {
    return this.name
  }
}
var getName = myObj.getName;
console.log(getName())// globalName

*  有一个局部的callback方法,callback被作为普通函数调用时,callback内部的this指向了window。代码如下:

<html>
  <body>
    <div id="div1">
     	 我是一个div 
    </div>
  </body>
  <script>
  	window.id = 'window'
    document.getElementById('div1').onClick = function() {
      console.log(this.id) // div1
      var callback = function() {
				console.log(this.id) // window
      }
      callback();
    }
    
    // 用一个变量保存div节点的引用
     document.getElementById('div1').onClick = function() {
      console.log(this.id) // div1
       var that = this;
      var callback = function() {
				console.log(this.id) // div1
      }
      callback();
    }
  </script>
</html>

在ECMAScript5的strict模式下,这种情况下的this被规定为不会指向全局对象,而是undefined。代码如下:

function func() {
  'use strict';
  console.log(this) // undefined
}
func()

3. 构造器调用

JavaScript中没有类,但是可以从构造器中创建对象,同时也提供了new操作符,使得构造器看起来更像一个类。

当用new运算符调用函数时,该函数总会返回一个对象,通常情况下,构造器里的this就会指向返回的这个对象。代码如下:

var MyClass = function() {
  this.name = 'summer'
}
var obj = new MyClass()
console.log(obj.name)// summer

使用new调用构造器时,还要注意一个问题,如果构造器显式地返回了一个object类型的对象,那么此次运算结果最终会返回这个对象。代码如下:

var MyClass = function() {
  this.name = 'summer'
  return {
    name: '夏天'
  }
}
var obj = new MyClass()
console.log(obj.name) // 夏天

如果new调用构造器时,不显式地返回任何数据,或者是返回一个非对象类型的数据,就不会引起上述问题。代码如下:

// 不显式地返回任何数据
var MyClass = function() {
  this.name = 'summer'
}
var obj = new MyClass()
console.log(obj.name) // summer

// 返回一个非对象类型的数据
var MyClass = function() {
  this.name = 'summer'
  return '夏天'
}
var obj = new MyClass()
console.log(obj.name) // summer

4. Function.prototype.call 或 Function.prototype.apply调用

跟普通函数调用相比,调用Function.prototype.call 或 Function.prototype.apply可以动态地改变this的指向。代码如下:

var obj1 = {
  name: 'summer',
  getName: function() {
    return this.name
  }
}

var obj2 = {
  name: '夏天'
}

console.log(obj1.getName())// summer
console.log(obj1.getName.call(obj2))// 夏天
console.log(obj1.getName.apply(obj2))// 夏天

call和apply方法能很好地体现JavaScript的函数式特性,在JavaScript中,几乎每一次编写函数式风格的代码,都离不开call和apply。

参考书籍:《JavaScript设计模式与开发实践》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值