什么是this?
this
关键字是一个非常重要的语法点。this
可以用在构造函数之中,表示实例对象。除此之外,this
还可以用在别的场合。但不管是什么场合,this
都有一个共同点:它总是返回一个对象。简单说,this
就是属性或方法“当前”所在的对象。
this.name
上面代码中,this
就代表name
属性当前所在的对象。
由于对象的属性可以赋给另一个对象,所以属性所在的当前对象是可变的,即this
的指向是可变的。
只要函数被赋给另一个变量,this
的指向就会变。
为什么要有this?
JavaScript 语言之所以有 this 的设计,跟内存里面的数据结构有关系。
var obj = { a: 5 };
上面的代码将一个对象赋值给变量obj
。JavaScript 引擎会先在内存里面,生成一个对象{ a: 5 }
,然后把这个对象的内存地址赋值给变量obj
。也就是说,变量obj
是一个地址(reference)。后面如果要读取obj.a
,引擎先从obj
拿到内存地址,然后再从该地址读出原始的对象,返回它的a
属性。
原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象
绑定this的方法
Function.prototype.call()
函数实例的call
方法,可以指定函数内部this
的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。
var obj = {};
var f = function () {
return this;
};
f() === window // true
f.call(obj) === obj // true
Function.prototype.apply()
apply
方法的作用与call
方法类似,也是改变this
指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数,使用格式如下。
func.apply(thisValue, [arg1, arg2, ...])
apply
方法的第一个参数也是this
所要指向的那个对象,如果设为null
或undefined
,则等同于指定全局对象。第二个参数则是一个数组,该数组的所有成员依次作为参数,传入原函数。原函数的参数,在call
方法中必须一个个添加,但是在apply
方法中,必须以数组形式添加。
Function.prototype.bind()
bind()
方法用于将函数体内的this
绑定到某个对象,然后返回一个新函数。
var a = new Date();
a.getTime() // 1481869925657
var x = a.getTime;
x() // Uncaught TypeError: this is not a Date object.
上面代码中,我们将a.getTime()
方法赋给变量x
,然后调用x()
就报错了。这是因为getTime()
方法内部的this
,绑定Date
对象的实例,赋给变量x
以后,内部的this
已经不指向Date
对象的实例了。