说道 JavaScript
高大上的技巧,this
关键字莫过之一了,而且 this
的使用频率相当高。不同与 Java
中 this
的三种用法,JavaScript
的 this
明确说只有一种用法,那就是 指向调用函数的对象 。下面分三种情况讨论:
作为对象方法调用
var obj = {
x: 0,
foo: function(x) {
this.x = x;
}
};
obj.foo(10);
console.log(obj.x); //10
这一种情况, this
绑定了调用函数的 obj
对象
作为函数调用
这种情况其实和第一种情况类似,请看:
var x = 0;
function foo(x) {
this.x = x;
}
foo(10);
console.log(this.x); //10
这里的 this
指向了全局 window
, 类比第一种情况,可以写成这样(假设可以):
var window = {
x: 0,
foo: function(x) {
this.x = x;
}
};
window.foo(x);
console.log(this.x); //10
呵呵~~看出个所以然了吧,这不就是把全局 window
当做 this
绑定的对象嘛!
还有一种特例就是,对象函数的内部函数会丢失当前对象 this
的引用,请看:
var obj = {
x: 0,
foo: function(x) {
var boo = function(x) {
this.x = x;
};
boo(x);
}
};
obj.foo(10);
console.log(obj.x); //0
console.log(this.x); //10
明显,boo
函数的 this
指向了全局 window
, x
的值并没有因此改变。遇到这种情况,可以这样解决:
var obj = {
x: 0,
foo: function(x) {
var that = this; //保存当前this引用
var boo = function(x) {
that.x = x;
};
boo(x);
}
};
obj.foo(10);
console.log(obj.x); //10
这里用一个 that
变量保存了 this
引用,以致于 that
指向当前对象。
作为构造函数调用
function Foo(x) {
this.x = x;
}
var foo1 = new Foo(10);
console.log(foo.x); //10
当构造函数被实例化时,this
自动指向实例化对象。
总结以上三种情况,都归结于一句话:this
指向调用函数的对象。
apply() 和 call()
最后,说一下 JavaScritp
提供的改变 this
绑定的方法 apply()
和 call()
。这两个方法都接收两个参数:要应用的对象和传入的参数,它们唯一的区别是 apply()
的参数传入一个数组,call()
只能一个一个的传入参数。知其一必知其二,下面我们拿 apply()
说事:
var obj = {
x: 10,
y: 10
};
var foo = function() {
return this.x - this.y;
};
console.log(foo.apply(obj)); //0
函数 Foo
绑定了对象 obj
,于是 this
指向 obj
,这是 apply()
最简单的用法。
apply()
还有一个很有用的用法,说明一下:
var array = [1, 2, 3, 4, 5];
console.log(Math.max.apply(null, array)); //5
console.log(Math.min.apply(null, array)); //1
数组被传入 Math.max()
和 Math.min()
方法中,第一个参数置空,表示没有对象调用。它们返回了数组的最大值和最小值