document.write("
**************一.指代當前對象**********************");function print(str){document.write(str+"
");};/*javascript裡面的this可謂是所有語言裡最讓人費解的了,學習國java或者php的人在學習javascript的時候會覺得非常莫名其妙,因為它不是物件導向的.而且它的複雜度也是貫穿javascript函數式編程的核心之一.記住最重要的一句話.如下:javascript中的this可能指代當前對象,也可能不是其簡單分析如下:一.指代當前對象1.指代當前對象如:在表單操作中使用this來指代當前的dom對象2.指代當前建構函式執行個體3.指代當前對象直接量4.指代全域對象二.指代當前範圍*///1.指代當前對象var obj = new Object();obj.name = "felayman1";obj.getName = function(){return this.name;};print(obj.getName());//2.指代當前建構函式執行個體function Template(){this.name = "felayman2";}var instanll = new Template();print(instanll.name);//指向建構函式的執行個體// 3.指代當前對象直接量var object = {"name":"felayman3","age":22,getName:function(){return this.name;},getAge:function(){return this.age}};print(object.getName()+object.getAge());// 4.指代全域對象print(this);print("*******************二.指代當前範圍********************************");var func = function(){print(this);};func();//會列印出object Windowprint((typeof func));//此時是functionprint((typeof func()));//window和undefined 因為函數調用完成後不屬於某個類型document.write("***********對象************
");print(new func());//會列印出objectprint(typeof(new func()));//這裡是兩個object,因為有了具體的引用對象/*分析:當直接調用函數的時候,瀏覽器會直接把該函數解析成一個普通的函數調用,去執行函數內部的代碼,或許有人在這裡會覺得this就指向func函數,或者是它的一個指標或者控制代碼,很可惜都不是,這與javascript引擎的記憶體模型有關,我們都知道javascript是解釋性語言,而非編譯型的,因此瀏覽器遇到的所有javascript代碼都會按照特定的步驟或者順序來執行代碼,引擎在載入一個指令碼後,會首先提取那些由var聲明的變數或者函數(只是全域環境下的),把提取到的變數儲存在一個暫存資料表中,我們可以理解成一塊記憶體地區,然後才會去逐行解析代碼,在解析的過程中,碰到函數調用會去暫存資料表中尋找對應的函數,當然引擎是很智能的,能判斷出要執行的是普通的函數調用,還是對象的建立(只針對此例子),因此,在javascript我們對於函數和對象還是分開的,其實可以這麼理解,函數就是類模板,而對象就是類模板的一次執行個體.類模板的類型屬於函數,而對象的類型屬於object.而正是this的這種特性,造就了this在函數閉包中的強大功能.如下例子*/print("********************************************");function f(){return this;}//定義一個嵌套的字面量var obj = {"name":"對象0bj","getThis":f(),"obj1":{"name":"對象obj1","getThis":f(),"obj2":{"name":"對象obj2","getThis":f()}}};print(obj.obj1.obj2.name);//表明可以擷取到obj對象屬性//將Obj2對象的函數指向過渡給personprint(obj.getThis);//輸出windowprint(obj.obj1.getThis);//輸出windowprint(obj.obj1.obj2.getThis);//輸出window/*對於上面的結果,如果我們不給明顯對比的例子,可能我們很難理解我想要表達的的是什麼,在此,我先不解釋上面的例子,我再給出下面的一個例子,產生對比來比較兩個例子的異同來分析*/print("********************************************");function ff(){return this;}var object = {"name":"對象0bject","getThis":ff,"object1":{"name":"對象0bject1","getThis":ff,"object2":{"name":"對象0bject","getThis":ff}}};print(obj.obj1.obj2.name);//表明可以擷取到obj對象屬性//將Obj2對象的函數指向過渡給personprint(object.getThis());//輸出objectprint(object.object1.getThis());//輸出objectprint(object.object1.object2.getThis());//輸出object/*這樣以來,結果就出來了,如果不細心的讀者還沒看出兩個例子有什麼區別的確,區別不是很大,但是其結果卻截然不同我們來分析一下:在第一個例子中,我們在為字面量對象添加方法的時候,請注意,我寫的是帶括弧的,帶括弧是什麼含義呢?函數調用,這裡我們要明白一個道理,字面量對象不是函數,它在對象確定的時候,內部所有屬性和方法都會存入到該對象的記憶體塊中,其方法內的可執行代碼會先被解析器解析好,只儲存最終結果,因此上述的getThis方法指向的是一個函數調用,因此只會保留該函數的最終結果而這個最終結果所返回的結果恰好是我們最開始例子的說明,其傳回值是一個window全域對象.因此導致字面量對象以及其屬性對象的getThis都指向該window對象.而在第二個例子中,我們的getThis只是複製ff函數的一個引用,而不是指向ff函數的的結果,因為此時該函數原型被提取到暫存資料表中,並沒有被瀏覽器解析,而是等到調用該函數的時候才會去解析它,當js引擎遇到object.getThis()的是才會去執行相應的代碼,而此時的環境已經發生變化了,再執行ff函數的時候,返回的this就會指向當前包含它環境的對象,因此會返回不同的object,而這個特性正是閉包的強大點,我們可以構建不同層次的閉包函數來改變this所指向的對象或者環境,以此來搭建更加複雜的函數模型,這就是後面我們要說的函數式編程.*/