javascript筆記:深入分析javascript裡對象的建立(中)

來源:互聯網
上載者:User

  深入分析javascript裡對象的建立這個小系列是我整個部落格裡最受歡迎的文章,有博友催我把下篇寫完,昨天和今天整理資料發現一篇文章還真講不完我下半部分的內容,所以把本來打算寫的下篇分成兩部分了。

  本主題的上篇裡我講到了三種對象建立的方式,最後通過類比java物件導向的思想反過來理解javascript對象的建立。如果根據標題的核心對象的建立,我所闡述的問題其實已經講完,但是我寫完上篇時候總覺得欠缺點啥,欠缺我的標題裡面的深入分析二字。小小的建立一個javascript對象它所包含的技術的延伸面是極其寬泛的,到了實際開發時候沒有一定發散的知識的積累我們想還會碰到難以理解的問題,中篇和下篇我想從我前一篇講到的知識拓展開這個問題。

  1.類的屬性和方法的另一種理解

  上篇裡面我寫到一句話:“一.屬於類的屬性和方法:用對象初始化的方式都可以當做是屬於類的屬性和方法,這種定義在jQuery裡面大量運用。”

  大家知道在java裡面類可以具有靜態屬性和方法,無需執行個體化該類的對象,就可以訪問這些屬性和方法,但是javascript裡面是不是只有通過對象初始化方式才會類比出這樣的特點了?其實不然,在程式設計語言裡,類的方法和屬性比較標準的叫法是:靜態範圍定義的屬性和方法任何時候都能從同一個位置訪問。其實嚴格意義上說javascript是沒有靜態範圍,對象初始化可以產生這樣的效果,但是它太不直觀了,前面的博文裡我講到javascript語言設計時候省略的類這個定義,而是把類的定義賦予到了建構函式裡面,那麼我們可以這樣思考,要想讓javascript語言裡有屬於類的屬性和方法,最佳的展現形式就是讓建構函式本身具有屬性和方法,大家看下面代碼:

 

function JsObj()
{
this.sayHello = function(){
console.log('Hello World!!!');
}

}

JsObj.whosay = function(){
console.log('sharpxiajun say Hello World!!!');
}

JsObj.whosay();
var obj = new JsObj();//sharpxiajun say Hello World!!!
obj.sayHello();//Hello World!!!

  這種寫法體現類的靜態屬性和方法特點會更加清晰些,前不久有人告訴我javascript裡面的物件導向的做法現在已經成為了一種實現物件導向的標準,有些新語言現在就借鑒javascript來設計自己的物件導向的機制,但是我另可不去相信這個說法,我還是願意把java的方式作為物件導向的標準方式,而javascript只是用類比方式來實現,如果真讓我把javascript物件導向做為一個新標準來理解,慣性的思維可能很難讓我對javascript物件導向的做法有更加清晰的認識。如果說上面代碼所運用的原理無非是javascript裡面函數就是對象,同樣可以為其賦值或者授予方法。這個問題很簡單,也很好理解,我這裡拿出這段代碼是想告訴大家,我在讀一些經典架構源碼時候,有些設計思想就是運用了這種寫法,但是我卻沒有把他們當作靜態變數來理解,導致有些代碼沒有讀懂。

  2.關於this指標的問題

  這是javascript最最最重要的一個概念,它的用法是掌握javascript精髓的關鍵。我們先看看下面這句話很關鍵,它道出了this用法的精髓:

  關鍵字this的用法:它用在對象的方法中,this總是指向調用該方法的對象。

  這句話道出了this是存在於對象的方法,裡麵包含兩個內容:對象和方法,方法屬於對象,樣本格式就是:

 

var obj = {};//或者var obj = new Object();二者等價
obj.nation = 'China';
obj.say1 = function()
{
console.log(obj.nation);
}
obj.say2 = function()
{
console.log(this.nation);
}

obj.say1();//China
obj.say2();//China

  結果一樣,這個正好體現了this使用在對象方法中,this總是指向調用該方法的對象。這是對this用法的標準定義,但是真的把這個概念理解透還真的下功夫,下面我拋開這個定義,列舉我所知道的this的用法。

  用法一:在函數中的使用

 

function JsObj()
{
this.nation = 'China';
console.log(this.nation);
}
JsObj();//China

  那麼這個this指向的是JsObj函數嗎?回答是NO,this指向的是window,看下面代碼:

 

function JsObj()
{
this.nation = 'China';
console.log(this.nation);
}
JsObj();//China

console.log(nation);//China
console.log(window.nation);//China
console.log(this.nation);//China

  看到效果了吧,指向的是window,我想有些童鞋可能不太理解為什麼,沒關係,這個疑問會引出我下一個小節要講的內容。

  用法二:作為對象方法的調用

  這個用法和我最開始講this指標的用法類似,代碼如下:

 

function say()
{
console.log(this.nation);
}

var obj = {};
obj.nation = 'China';
obj.objSay = say;
obj.objSay();//China

  用法三:作為建構函式的調用

  說道javascript建構函式,我就要反覆再強調一個基礎知識:在javascript裡的建構函式包含了類的特性。下面看我寫的代碼:

 

function JsObj()
{
this.nation = 'China';
}
var obj = new JsObj();
console.log(obj.nation);//China

  這個nation絕對不屬於window了,大家信不信了?我們可以測試一下:

 

var nation = 'USA';
function JsObj()
{
this.nation = 'China';
}
var obj = new JsObj();
console.log(obj.nation);//China
console.log(nation);//USA

  用法四:apply調用時候的this

  apply()是函數對象的一個方法,它的作用是改變函數的調用對象,它的第一個參數就表示改變後的調用這個函數的對象。因此,this指的就是這第一個參數。測試代碼如下:

 

var nation = 'USA';
function say()
{
console.log(this.nation);
}
var obj = {};
obj.nation = 'China';
obj.objSay = say;
obj.objSay.apply();//USA
obj.objSay.apply(obj);//China

  apply()的參數為空白時,預設調用全域對象。因此,這時的運行結果為USA,證明this指的是全域對象。apply傳入obj對象,this就指向了對象obj了,啟動並執行結果是China。

  3.執行環境及範圍

  我在上面總結javascript裡this用法時候提出了一個問題,為什麼this指向了window,解釋這個問題就會牽涉出javascript裡面有一個非常重要的概念執行環境及範圍

  首先說道的是執行環境,什麼是執行環境呢?在javascript裡面執行環境分為兩類,一類是全域環境,一類是局部環境,整個頁面裡被共用的方法和屬性就是在全域環境,相對於全域環境,函數{}號裡的執行環境就是局部環境,執行環境定義了變數或函數有權訪問的其他資料,決定了它們各自的行為,每個執行環境都定義了一個與之相關的變數對象,環境中定義的所有變數和函數都儲存在這個對象裡,雖然我們自己編寫的代碼無法訪問這個對象,但解析器在處理資料時候後台會使用到它

  全域執行環境另一種說法是最外圍的一個執行環境,在web瀏覽器的範圍中(actionscript也是施行了ECMAScript標準,它的全域範圍就和javascript的全域範圍不同),全域執行環境被認為是window對象,因此全域變數和函數都是作為window對象的方法和屬性來建立的,全域執行環境知道應用程式退出比如關閉網頁或瀏覽器才會被銷毀。而局部環境則是以函數對象作為關聯對象。

  javascript語言規定了全域執行環境和局部執行環境的概念,這就產生了一個極其重要的應用:範圍鏈。當代碼在一個環境裡面被執行的時候會建立變數的對象構成的範圍鏈,它的用途是保證對執行環境有權訪問所有變數和函數的有序訪問。範圍鏈的前端始終是當前執行代碼所在的環境的變數對象。如果這個環境是函數,則將其使用中的物件作為變數的對象,使用中的物件在最開始時只包含一個變數,就是arguments對象,arguments在全域環境中是不存在的,範圍鏈的下一個對象來自包含前一個對象的外部環境,而再下一個變數對象則來自下一個包含環境,如此類推,一直延續到全域環境,全域環境永遠是範圍鏈最後一個對象。

  呵呵,看這個解釋是不是有點暈啊,我想換個角度思考可能好理解點,在javascript裡,所有的屬性和方法都是屬於某一個對象的,其實在javascript裡面,所有方法或屬性的調用都是obj.method(),obj.name樣式,如果程式碼裡調用屬性或方法時候找不到這個調用對象,javascript解析器就會往函數範圍的上層範圍裡找,直到window全域環境,實在找不到的就預設授予給window對象。

  好了,今天內容就寫到這麼多吧,真沒想到javascript一個個看起來簡單的對象建立能延伸出這麼多知識,回味下這種點到面的研究方法還是蠻不錯的,最近做java太多(我最近想開起一個新系列,我一直想做的系列android,不過有人跟我說一個人精力有限,我還是先把沒寫完的東西寫完),寫javascrip的激情有點不夠了,真希望有一個全職做前端的環境,不過java也是很有趣的,最近和博友交流後我越加有動力把三套javaEE架構寫完,給自己打打氣,加油了。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.