日期:2014-05-16  浏览次数:20471 次

JavaScript keyword 'this' 你真的懂吗?
  正题之前想问大家几个问题先。
  1.写过JS代码,而没用过this关键字的童鞋们请举手.
  2.已用过N加1次this关键字,但认为自己对this的理解不正确的请举手.

  有人举手吗?有人举两次手吗? 有吗,真的有吗? 相信是没有滴,无论是生理上还是心理上。这种心态太正常了:-) 符合期望值。
  但是呢...? 我们的目前对this的理解真是都是正确的吗? 我看未必,不信的话你可以和自己打赌,输的请赢的吃饭,之后再考考身边的同事们,看看他们的答案^__^

   OK不扯了,进入正题, 一例胜万言。
 
function person(name){
    this.__name = name;
    function sayHello(){
        alert("Hello,this is " + this.__name);
    }
    sayHello();
}

// 执行下一行的效果是 alert("Hello,this is spring") 大家都猜到了吧。一个声音:"这还用的着猜吗? OOXX"。
//别急,继续向下看。

person("spring");

//那这一行呢?
//1. 'person("spring")'都执行完了,__name早都没了
//2.  况且__name是属于person的一个属性,你在这直接写alert(__name), 就是person还存在,在它function体外也访问不到啊。
// OK, 如何是各位的理解是如此的话,请试着在你的 Chrome, Firefox 或 safari //browser中执行一下。

alert(__name)



//怎么样?什么情况呢现在? 少许的茫然...
//没关系, 再试一下下面几行

alert(this.__name)
alert(this)
alert(this === window)

  为了让大家更看清this的真实面目, 我们对上面的function进行了一点改造.

function person(name){
    this.__name = name;
    function sayHello(){
        alert("Hello,this is " + this.__name);
    }
    //sayHello();
    return this;
}

//OK 现在再试下
alert(this === person("spring") )

//现在明白了吧, 心想:"丫的this你原来指向的是window对象啊, 骗我那么久,现在终于明白了!"
// 别急下定论,继续向下试

var oneGuy = new person("cute");
alert(__name);  

//"还不是alert出来__name的值嘛, 和上面神马区别?",  对!就是因为完全没区别这才是大问题。
//再试执行一次仔细看看alert 出来的值是什么, 请看清楚是....spring, 而不是.... cute。大家要注意哦,我们最新传入的值可是cute而不是spring哦。不知道为什么没关系,再试...


alert(this === oneGuy)
//  false, 竟然是false! WHY???


   好了,例子就试到着先。 现在来说说为什么。这有两个概念需要澄清:
1. JavaScript的确是script即脚本语言,但不妨碍它是面向对象的语言。我们所有的变量声明,function定义,对象创建都是基于某一个对象

结点之上进行的。

2. 虽然JS是很活很强大,但也多少有一点点让人confused, 就function这一keyword而言, 它是可以一字两用的(多意字^_^)。
    a. 以 new person()出现时, 这时person表示的是person这个'class'的constructor---如同Java Class的constructor一样的概念。
    b. 以 function person("abc...")形式出现时,就只被认为是在其被定义对象节点上普通的一个方法如Java语言中的no-static method.

将两点结合到一起看呢来解决我们上面例子中出现的现象就好理解了。
1. 直接当method用时, 那么因为person这个方法是在当前对象节点window上定义或说声明的, 那么对用Java的童鞋们是显而易见的,no-

static method体中的this必然指向的是方法所被声明的对象实例(instance)本身,此处即window.

2. 而当constructor用时,可以理解为是在window对象实例上创建了个内部类的实例person对象(而不再是method), 那么实例化的person对象中的this肯定要指向它自己啦。


   最后总结,总而言之,总而言之。
一,要理解面向对象语言共有的对象实例的树形结构.
obj_0:
{
var v1,v2,v3;
function f1,f2,f3;
subObjectInstance obj_0_0 : {...},
                 obj_0_1 : {...},
                 obj_0_2 :
                          {
                          var v1,v2...;
                           function f1,f2.....;
                          subObjInstance obj_0_2_0 : {...},    obj_0_2_1 : {...},
 &nb