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编程语言中,它明确的定义为对象本身,在运行期间可以不断改变)。


到这里就结束了~\(≧▽≦)/~

如果有问题,请指出~~

posted @ 2013-09-11 15:21  糜基  阅读(506)  评论(0)    收藏  举报