this 关键字
作用
this可以用在构造函数之中,表示实例对象( javascript对象篇有提及, 非常简单易懂)
this
有一个特点:它总是返回一个对象
。this
就是属性或方法“当前”所在的对象。
this.property // this此时就代表property属性当前的对象。
下面是一个实际的例子。
var person = { name: 'xiaobai', describe: function () { return 'name:'+ this.name; } }; person.describe() // "name:xiaobai"
由于this.name
是在describe
方法中调用,而describe
方法所在的当前对象是person
因此this
指向person
,this.name
就是person.name
。
由于对象的属性可以赋给另一个对象,所以属性所在的当前对象是可变的,即this
的指向是可变的。
var A = { name: 'daitu', describe: function () { return 'name:'+ this.name; } }; var B = { name: 'xiaobai' }; B.describe = A.describe; B.describe() // "name:xiaobai"
上面代码中,A.describe
属性被赋给B
,于是B.describe
就表示describe
方法所在的当前对象是B
,所以this.name
就指向B.name
。
使用
全局环境
function f() { console.log(this === window); } f() // true
不管是不是在函数内部,只要是在全局环境下运行,this
就是指顶层对象window
。
构造函数
构造函数中的this
,指的是实例对象。
var Obj = function (p) { this.p = p; };
上面代码定义了一个构造函数Obj
。由于this
指向实例对象,所以在构造函数内部定义this.p
,就相当于定义实例对象有一个p
属性。
var o = new Obj('Hello World'); o.p // "Hello World!"
对象的方法
如果对象的方法里面包含this
,this
的指向就是方法运行时所在的对象。该方法赋值给另一个对象,就会改变this
的指向。
这条规则不容易把握
var obj ={ foo: function () { console.log(this); } }; obj.foo() // obj
上面代码中,obj.foo
方法执行时,它内部的this
指向obj
。
但是,下面这几种用法,都会改变this
的指向。
// 情况一 (obj.foo = obj.foo)() // window // 情况二 (false || obj.foo)() // window // 情况三 (1, obj.foo)() // window
上面代码中,obj.foo
就是一个值。这个值真正调用的时候,运行环境已经不是obj
了,而是全局环境,所以this
不再指向obj
。
可以这样理解,JavaScript 引擎内部,obj
和obj.foo
储存在两个内存地址,称为地址一和地址二。
obj.foo()
这样调用时,是从地址一调用地址二,因此地址二的运行环境是地址一,this
指向obj
。
但是,上面三种情况,都是直接取出地址二进行调用,这样的话,运行环境就是全局环境,因此this
指向全局环境。上面三种情况等同于下面的代码。
// 情况一 (obj.foo = function () { console.log(this); })() // 等同于 (function () { console.log(this); })() // 情况二 (false || function () { console.log(this); })() // 情况三 (1, function () { console.log(this); })()
如果this
所在的方法不在对象的第一层,这时this
只是指向当前一层的对象,而不会继承更上面的层。
简单说明this使用需要避免的问题
- 避免多层this
- 避免数组处理方法中的this
- 避免回调函数中的this