this是Javascript言语的一个关键字。
它代表函数运转时,自动天生的一个内部对象,只能在函数内部运用。比方,
function test(){
this.x = 1;
}
跟着函数运用场所的差别,this的值会发生变化。
有一个总的准绳,那就是this指的是,挪用函数的谁人对象。
下面分四种状况,细致议论this的用法:
状况一:地道的函数挪用
这是函数的最一般用法,属于全局性挪用,因而this就代表全局对象Global。
1)请看下面这段代码,它的运转效果是1。
function test(){
this.x = 1;
alert(this.x);
}
test(); // 1
为了证实this就是全局对象,我对代码做一些转变:
var x = 1;
function test(){
alert(this.x);
}
test(); // 1
运转效果照样1。再变一下:
var x = 1;
function test(){
this.x = 0;
}
test();
alert(x); //0
2)接下来剖析匿名函数下的状况(博客内容外的自增加):
var name="the window";
var object={
name:"My object",
getNameFunc:function(){
return function(){
return this.name; //没有被直接挪用,此匿名函数的实行环境具有全局性
}; }
};
alert(object.getNameFunc()());//the window(非严厉形式下)
状况二:作为对象要领的挪用
函数还能够作为某个对象的要领挪用,这时刻this就指这个上级对象。
function test(){
alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); // 1
状况三 作为组织函数挪用
所谓组织函数,就是经由过程这个函数天生一个新对象(object)。这时刻,this就指这个新对象。
function test(){
this.x = 1;
}
var o = new test();
alert(o.x); // 1
运转效果为1。为了表明这时刻this不是全局对象,我对代码做一些转变:
var x = 2;
function test(){
this.x = 1;
}
var o = new test();
alert(x); //2
运转效果为2,表明全局变量x的值基础没变。
状况四 apply挪用
apply()是函数对象的一个要领,它的作用是转变函数的挪用对象,它的第一个参数就示意转变后的挪用这个函数的对象。因而,this指的就是这第一个参数。
var x = 0;
function test(){
alert(this.x);
}
var o={};
o.x = 1;
o.m = test;
o.m.apply(); //0
apply()的参数为空时,默许挪用全局对象。因而,这时刻的运转效果为0,证实this指的是全局对象。
如果把末了一行代码修改成
o.m.apply(o); //1
运转效果就变成了1,证实了这时刻this代表的是对象o。
----------摘自阮一峰博客
另附笔者看法:
This对象是在运转时基于函数的实行环境绑定的:在全局函数中,this即是window,而当函数作为某个对象的要领挪用时,this即是谁人对象。不过,匿名函数的实行环境具有全局性,因而其this一般指向window。然则因为闭包编写体式格局差别,效果没有那末显著。
别忘了:有一个总的准绳,那就是this指的是,挪用函数的谁人对象。
例1. 匿名函数没有被直接挪用,匿名函数的实行环境具有全局性,this指的是window对象
var name="the window";
var object={
name:"My object",
getNameFunc:function(){
return function(){
return this.name;
};//没有被直接挪用,此匿名函数的实行环境具有全局性
}
};
alert(object.getNameFunc()());//the window(非严厉形式下)
例2.匿名函数被直接挪用,this指的是挪用它的对象
var name="the window";
var object={
name:"My object",
getNameFunc:function(){
return this.name;
};//被getNameFunc(也就是object)挪用
}
};
alert(object.getNameFunc()());//My object(非严厉形式下)
例3.经由过程that绑定实行环境对象(this是关键字,而that不是关键字)
var name="the window";
var object={
name:"My object",
getNameFunc:function(){
var that=this;//经由过程that绑定了object对象 ;object <--getNameFunc(name)
return function(){
return that.name;//建立闭包,返回that.name
};//object下的name
}
};
alert(object.getNameFunc()());//My object(非严厉形式下)
模拟块级作用域(私有作用域):
语法以下:
(function(){
//这里是块级作用域
})();
以上代码定义而且马上挪用了一个匿名函数。将函数声明包含在一对圆括号中,示意它实际上是一个函数表达式。而紧随其后的另一对括号会马上挪用这个函数。
类似于:
var someFunction=function(){
//这里是块级及作用域
};
someFunction();
这里定义了一个函数(匿名函数,并把值赋给someFunction)然后马上挪用了它(在函数称号背面增加一对括号)。
下面来看另一种不加括号的状况:
function(){//dosomething}();
例:function (){alert("Hi")}();
这段代码会致使语法毛病,是因为javascript将function关键字看成一个函数声明的最先,而函数声明背面不能跟圆括号。而表达式背面能够跟圆括号,要将函数声明变成表达式,只需向下面那样给它加一对圆括号即可:
(function(){
//这里是块及作用域
})();
如:(function (){alert("Hi")}());
注:
1.result=function(){//dosomething}(); 这个匿名函数后加括号不会报错而且匿名函数会马上实行。
2.result=function(){//dosomething}()与function(){//dosomething}()两个语句完整差别,前者是有赋值的。
3.可行缘由是这里的赋值js实际上把匿名函数看成表达式处理了,表达式背面能够加括号。
而且在function(){//dosomething}()前面加“-“、”!“等运算符还会依据运算划定规矩转变赋给result的值。
4.result=
function(){//dosomething}();
2.!function(){ // do something }();
3.~ function() {}();
4.+ function() {}();
5.- function() {}()
道理是语句function(){//dosomething}()都被看成表达式处理了(赋值前盘算表达式的值),就是2、3、4、5例能够自实行,自实行的缘由也是function(){//dosomething}()因为前面的标记被看成表达式处理了
。
私有作用域实例:
function outputNumbers(count){
(function(){
for(var i=0;i<count;i++){
alert(i);//块级作用域
}
})();
alert(i);//会致使一个毛病,i已被销毁了
}
outputNumbers(5);//0,1,2,3,4
//抛出毛病
面试题剖析:
1.
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);
答案:"undefined"
在arguments[0]()中实行了一个要领,arguments[0]就是foo.bar要领
注重: foo.bar作为团体传入函数中,然则foo.bar中的this是没有绑定到foo,虽然 foo.bar 通报给了函数,然则真正实行的时刻,函数 bar 的上下文环境是 arguments ,并非 foo。(foo.bar作为团体的通报体式格局解除了foo对bar的挪用作用)
arguemnts[0] 能够理解为 arguments.0(不过写代码就不要如许了,语法会毛病的),所以如许看来,上下文环境是 arguemnts 就没问题了,所以在实行baz的时刻天然this就是window了,window 上没有baz属性,返回的就是undefined, typeof挪用的话就转换成”undefined”了
这里的 this 指的是 arguments,经测试确切云云:
2.
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();
答案:"undefined"
类似于
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
f = foo.bar;
typeof f();
把foo.bar存储给f然后挪用,所以this在foo.bar援用的是全局对象,所以就没有baz属性了
换句话说:foo.bar实行的时刻上下文是 foo,然则当 把 foo.bar 赋值给 f 的时刻,f 的上下文环境是 window ,是没有 baz 的,所以是 ”undefined"。
解决方案:应用闭包或许bind()
//函数绑定bind()
function bind(fn,context){//返回闭包
return function(){
return fn.apply(context,arguments);//arguments指函数内部的而非bind的
}
}
//测试
var handler={
message : "Event Handler",
handleClick : function(event){
alert(this.message);
}
}
//var documentFragment=document.createDocumentFragment();
var text='<button id="button">按钮</button>';
document.body.innerHTML=text;
var btn=document.getElementsByTagName("button")[0];
EventUtil.addHandler(btn,"click",bind(handler.handleClick,handler));