你所不知道的JavaScript(一)this 关键字

比起Java, C#等面向对象语言,this关键字在JS中有更多需要注意和理解的地方,下面就来一一看下几个场景的用法:

 

1. 跟 Java, C#等语言一样,this可以声明在构造函数里,用来定义成员变量

function foo(a) {
this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2


2. 如果不是作为new 的构造函数, this代表的是当前上下文的对象

function foo(num) {
    console.log( "foo: " + num );
    this.count++;
}

foo.count = 0;

var i;

for (i=0; i<10; i++) {
    if (i > 5) {
        foo( i );
    }
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9

console.log( foo.count ); // 0

上面的代码,foo.count 和this.count 不是一个变量, 在默认模式下,this.count创建了一个全局的变量,由于没有初始化,在++后变成NaN。 而在strict mode下, this.count会在运行时直接抛出undefined的错误

3. 隐式改变this

function foo() {
console.log( this.a );
}
var obj2 = {
a: 42,
foo: foo
};
var obj1 = {
a: 2,
obj2: obj2
};
obj1.obj2.foo(); // 42

this是当前上下文的对象,所以在obj1.obj2.foo()中,this指向的是obj2,所以this.a=obj2.a

 

4. 显式改变this

可以使用call, apply和bind三个方法来显示改变this

function foo() {
console.log( this.a );
}
var obj = {
a: 2
};
foo.call( obj ); // 2  obj并没有foo方法,使用foo.call把foo的强制绑定到obj的上下文

function foo(something) {
console.log( this.a, something );
return this.a + something;
}
var obj = {
a: 2
};
var bar = function() {
return foo.apply( obj, arguments );   //带参数的强制硬性绑定,无论调用环境如何,都会使用 obj 作为调用上下文
};
var b = bar( 3 ); // 2 3

//也可以用bind返回重新绑定过的函数,已供后面使用
function foo(something) {
console.log( this.a, something );
return this.a + something;
}
var obj = {
a: 2
};
var bar = foo.bind( obj );
var b = bar( 3 ); // 2 3
console.log( b ); // 5


function foo(el) {
console.log( el, this.id );
}
var obj = {
id: "awesome"
};

// use `obj` as `this` for `foo(..)

call和apply的区别仅仅是apply支持传递参数

《你所不知道的JS》对this做了很好的总结,优先级如下:

1. 如果是用new创建的this,就是新对象的成员函数: var bar = new foo()

2. 如果使用了call, apply或bind, 则为显式绑定,this指向call, apply或bind方法的第一个参数: var bar = foo.call(obj2 )

3. 隐式绑定: var bar = obj1.foo()

4. 默认的绑定,在strict模式下抛出undefined, 在普通模式下会生成全部变量: var bar = foo()

 

好了,规则都说完了,下面这段代码如果搞明白了,说明对this 的理解也过关了:

function foo(something) {
    this.a = something;
}
var obj1 = {
    foo: foo
};

var a = 4;
var obj2 = {};
obj1.foo(2);
console.log(obj1.a); 

foo(5);
console.log(a);  

obj1.foo.call(obj2, 3);
console.log(obj2.a); 
var bar = new obj1.foo(4);
console.log(obj1.a); 
console.log(bar.a);


 

原文: https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch1.md 

相关文章
相关标签/搜索