js的this对象解析
一直弄不懂js中this的指向,觉得变来变去很复杂,纠结啊╮(╯_╰)╭。看了很多其他人写的解释后,自己在这里总结一下。
总而言之:永远指向函数运行时所在的对象,而不是函数被创建时所在的对象。
如果处在匿名函数中、或者不处于任何对象中,this 都指向宿主的根对象(在浏览器里面就是 window)
Javascript 的 this 很花心,在哪个对象的家里,就是那个对象的。
而 C,C++,C# 的 this 很专一,无论在哪,都属于原配!
并且 Javascript 的函数作用域 则像出生地,出生在哪里,出生地就是哪里!和运行环境无关!
该总结来自:http://julying.com/blog/javascript-this/
主要参考:http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html
作为一个基础不扎实,理解不透彻的人,表示看上面的画后还是觉得鸭梨山大的不理解,所以我再分成下面几类
this指的是,调用函数的那个对象。即函数被谁调用,this就是谁。
一、作为函数时
1)纯粹的函数调用
function test(){ this.x = 1; alert(this.x); } test(); // 1
这是函数的最通常用法,属于全局性调用,this就代表全局对象Global。(想想看,这个函数写在html中的<script>中,或者一个单独的js文件中,最为js,它的上级没有其他东西,当值为null的时候,其值会被隐式转换为全局对象。注:第5版的ECMAScript中,已经不强迫转换成全局变量了,而是赋值为undefined。)
为了证明this就是全局对象,对代码做一些改变:
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
2)作为对象的方法调用
function test(){ alert(this.x); } var o = {}; o.x = 1; o.m = test; o.m(); // 1
以上代码等同于:
function test(){ alert(this.x); } var o = { x : 1, m : test } o.m(); // 1
以上是函数作为某个对象的方法调用,这时this就指这个上级对象。
二、作为构造函数时
所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。
var x = 2; function test(){ this.x = 1; } var o = new test(); alert(x); //2
运行结果为2,表明全局变量x的值根本没变。
———————————————————————————————————————————————————————
如果不清楚对象与构造函数的区别,我们就来简单的了解一下。
首先,我们看一下他们是什么样的,下面这是对象(这是经常使用的JSON形式):
var objJson={
op1:'objJson option1',
fn1:function(){
alert(this.op1)
}
}
在这种形式的声明下,你可以通过objJson.op1或者objJson.fn1()来直接访问内部的属性。
下面是构造函数:
var objFn = function(){
var pri1 = 'privateVar'; //私有变量
this.op1 = "publicVar"; //共有变量
this.op2 = function(){
alert(pril + ";" + this.op1);
};
}
var o = new objFn();
alert(typeof o.pril + ";" + typeof o.op1); //undefined,string
o.op2(); //出错,pri1没定义。
如果不new一个实例,而直接通过objFn.op1或者objFn.op2()方式来访问内部的属性的话,就不行了,因为这个时候他还不是个对象。
new是开辟一个新的空间;而直接使用“=”则是相当于改变指针的指向,是引用。new后,各自的属性不会因其他实例的改变而改变,而“=”后则会改变。
所以,如果按上边这样构造函数构建方法(单纯的构造函数模式),如上边的op2,则会使每个实例都有各自的op2方法,每个实例都占用了一个为这个函数使用的内存空间,所以要使用prototype属性,通过混合的构造函数/原型方式来定义对象。具体参见:http://www.cnblogs.com/inuka/p/3300574.html
———————————————————————————————————————————————————————
此外,看下下面这段代码:
var foo = { bar: function () { return this; } }; foo.bar(); // foo var test = foo.bar; test(); // global
这里第一个就如前面所说,是foo,而第二个我就有点混乱了。这段代码是来自:http://blog.sina.com.cn/s/blog_43c4e0ca010133v9.html 。来源的作者是通过引用类型的不同来判断的,因为我理解方式与大多数人的不同,也比较复杂,我就懒得看了,有兴趣的人可以去看看。
我的理解是,test指向了foo对象的bar属性。函数被谁调用,this就是谁。这里的test是在全局中,并不是new出(这里也不能new)的foo实例,所以此时它是被全局调用,this是全局对象Global。很可能我的理解有错误,请大家指出问题~
三、apply、call函数
如果是call()、apply()、with(),指定的this是谁,就是谁。如果第一个参数传入的对象调用者是null或者undefined或者参数为空时,默认把全局对象(也就是window)作为this的值。
var x = 0; function test(){ alert(this.x); } var o={}; o.x = 1; o.m = test; o.m.apply(); // 0.apply()的参数为空时,默认调用全局对象。 o.m.apply(o); // 1
四、具体分析this在控件event中的实际指向
1) 内联事件注册 。
将事件直接写在HTML代码中(<element onclick=”doSomething()”>), 此时this指向window对象 。
例如:
function doSomething(){ alert(this.value); }
<input id="but" type="button" onclick="doSomething()" value="test" />
运行这段代码页面弹出undefined字样。有人会说,我的input标签里面明明有value属性的值为test的。但是这里为什么会弹出undefined字样呢。
其实道理很简单,这里是通过onclick方法调用的。其实onclick="doSomething()",相当于function onclick(evenet){doSomething();}。
而function onclick其实也是一个全局的function,上面的 test方法也是全局的function,都可以视为window对象的两个属性。
这里其实就是通过这个在onclick方法里面调用这个test方法。其本质就是一、中1)纯粹的函数调用方式。
2) T传统事件注册 (DHTML方式)。
形如 element.onclick = doSomething;
window.onload = function(){ var but = document.getElementById("but"); but.onclick = function(){ alert(this.value); // this为该html元素 }; }
<input id="but" type="button" value="test" />
可以看出,此时的but为一个对象,在调动其自身的onclick属性,形同 一、中2)作为对象的方法的调用。所以此时的this是指but本身。
3) <element onclick=”doSomething(this)”>作为参数传递,可以通过参数指向element
function doSomething(obj){ alert(obj.value); //test alert(this.value); //undefined }
<input id="but" type="button" onclick="doSomething(this)" value="test" />
其实这个方式下,this跟1)是一样的,this都是全局对象window。只不过在html中,通过this把其自身作为参数传给了函数而已。
ps:
this值的首要特点(或许是最主要的)是它不是静态的绑定到一个函数。
this是进入上下文时确定,在代码运行时的this值是不变的,也就是说,因为它不是一个变量,就不可能为其赋值(相反,在Python编程语言中,它明确的定义为对象本身,在运行期间可以不断改变)。
到这里就结束了~\(≧▽≦)/~
如果有问题,请指出~~

浙公网安备 33010602011771号