您的位置:首页 > Web前端 > JavaScript

js中this的绑定

2016-08-07 10:52 246 查看
人们对于this的绑定常常有两个误解,一:指向函数本身,二:指向函数作用域。这两种想法都是错的,this并不指向函数本身,也不指向函数作用域。

复制代码

function foo(){

this.count++;

}

foo.count = 0;

for(var i = 0 ; i<5 ; i++){

foo();

}

alert( foo.count ); // 0

复制代码

因为this不指向函数本身,所以foo.count的值依然是0。

function foo(){

var a = 1 ;

alert(this.a);

}

var a = 2;

foo(); // 2

因为this不指向函数作用域,所以输出的是2。

this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

this的绑定一共有四种绑定:1:默认绑定(即没有明确的调用对象)

2:隐性绑定(即作为对象方法调用,this会被绑定到该对象)

3:显性绑定(使用apply()和call()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

4:new绑定(使用new来调用函数,会构造一个新对象,并且把this绑定到该对象)

一:默认绑定   (即没有明确的调用对象)

function foo(){

var a = 1 ;

alert(this.a);

}

var a = 2;

foo(); // 2 (非严格模式下)

没有明确调用对象,this会被绑定到window对象,所以this.a就是window.a,即为2。不过这得在非严格模式下,只有在非严格模式下this才会被绑定到window对象,而在严格模式下,this被绑定到undefined。

二:隐性绑定   (即作为对象方法调用,this会被绑定到该对象)

复制代码

function foo(){

var a = 1;

alert(this.a);

}

var obj = {

a:2,

foo:foo

};

obj.foo(); // 2

复制代码

obj对象调用foo()函数,this被绑定到obj对象,所以输出了obj对象的a的值2。

对象属性引用链中只有最后一层会影响调用位置

复制代码

function foo(){

alert(this.a);

}

var obj2 = {

a:2,

foo:foo

};

var obj1 = {

a:1,

obj2:obj2

};

obj1.obj2.foo(); //2

复制代码

obj1和obj2两个对象连续调用,this会被绑定到最后一个对象,即obj2,所以输出2

隐式丢失:被隐式绑定的函数会丢失绑定对象,有两种情况会丢失,一种为引用,另一种为回调函数。

引用:

复制代码

function foo(){

alert(this.a);

}

var obj = {

a:1,

foo:foo

};

var bar = obj.foo;

var a = "global 1";

bar(); //global 1

复制代码

bar是obj.foo的一个引用,实际上它引用的是foo函数本身,所以this被绑定到window对象,输出的是"global 1"

回调函数:

复制代码

function foo(){

alert(this.a);

}

function doFoo(fn){

fn();

}

var obj = {

a = 1,

foo:foo

}

var a = "global 1";

doFoo(obj.foo); //"global 1"

复制代码

调用回调函数的函数可能会修改this

三:显性绑定(使用apply()和call()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

复制代码

function foo(){

alert(this.a);

}

var obj = {

a:1

};

foo.call(obj); // 1

复制代码

call()的参数若为空,默认调用window对象,若为一个原始值(字符串类型,布尔类型或者数字类型),则这个原始值会被转换成它的对象形式(new String(),new Boolean() 或者 new Number()),这被称为“装箱”

硬绑定———显示绑定的一种变形

优点:可以解决丢失绑定问题

缺点:硬绑定后不可能再修改它的this

复制代码

function foo(){

alert(this.a);

}

var obj = {

a:2

};

var bar = function(){

foo.call(obj);

};

bar(); // 2

setTimeout(bar,100); // 2

bar.call(window); // 2

复制代码

ES5中提供了内置方法Function.prototype.bind

复制代码

function foo(something){

alert(this.a, something);

return this.a + something;

}

var obj = {

a:2

};

var bar = foo.bind(obj);

var b = bar(3); // 2 3

alert(b); // 5

复制代码

bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数

四:new绑定(使用new来调用函数,会构造一个新对象,并且把this绑定到该对象)

function foo(a){

this.a = a;

}

var bar = new foo(2);

alert(bar.a); // 2

this绑定的四条规则的优先级: new绑定 > 显示绑定 > 隐式绑定 > 默认绑定
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: