JavaScript概念總結:範圍、閉包、對象與原型鏈

來源:互聯網
上載者:User

1 JavaScript變數範圍

1.1 函數範圍

沒有塊範圍:即範圍不是以{}包圍的,其範圍完成由函數來決定,因而if /for等語句中的花括弧不是獨立的範圍。

如前述,JS的在函數中定義的局部變數只對這個函數內部可見,稱之謂函數範圍。

嵌套範圍變數搜尋規則:當在函數中引用一個變數時,JS會搜尋當前函數範圍,如果沒有找到則搜尋其上層範圍,一直到全域範圍。

var  value = 'global';var f1 = function(){  console.log(v1);   //global};f1();var f2 = function(){  var v1 ='local';  console.log(v1); //local};f2();

詞法範圍規則:函數的嵌套關係是定義時決定的,而非調用時決定的,即詞法範圍,即嵌套關係是由詞法分析時確定的,而運行時決定。

var v1 = 'global';var f1 = function(){  console.log(v1);  }f1();  //globalvar f2 = function(){  var v1 = 'local';  f1();};f2();  //global

對於這兩個規則的相互作用,函數內無論什麼位置定義的局部變數,在進入函數時都是已經定義的,但未初始化,即為undefined,直到運行到變數被賦值時才被初始化,因此若訪問了未初始化的變數,我們會得到undefined的說明。

var v1 = 'global';var f = function(){  console.log(v1);   //undefined  var v1 =  'local';};

1.2 全域範圍

全域範圍的變數是全域對象的屬性,不論在什麼函數中都可以直接存取,而不需要通過全域對象,但加上全域對象,可以提供搜尋效率。

滿足下列條件的變數屬於全域範圍:

在最外層定義的變數

全域對象的屬性

任何地方隱匿定義的變數。

2 閉包

2.1 裝飾的定義

function f1(){  //context define  function f2(){   //func define  };  return f2;};f2(); //獲得f1中的context

在類似C/C++這種的非函數式程式設計語言中,我們也可以定義函數指標並返回,但外層函數在執行結束後為內層函數定義的上下文資訊會被銷毀,而在閉包中,則儲存了返回的函數,還包含返回函數的上下文資訊。(由詞法範圍所支援)而且在返回閉包之後,上下文資訊即被單獨建立出來,從而可以產生多個互相獨立的閉包執行個體。

2.2 閉包的用途

閉包有兩個用途,一是方便實現嵌套的回呼函數,二是隱藏對象的細節。

對於前者,NodeJS的編程風格已經可以說明問題,對二後者,對於函數內部的局部變數外部是不可見的,但可以提供訪問函數來訪問和修改相應的局部變數,從而實現OO封裝的意圖。

3 對象

在基於類型的語言中,對象是由類執行個體化,而JS是基於原型的系統,對象是由原型複製產生的。

3.1 對象的建立與訪問

JavaScript中的Object實際上就是一個由屬性群組成的關聯陣列,屬性由名稱和值組成。可以由new Object()或{}來建立對象。對於建立簡單對象,可以使用對象初始化器來建立對象,即由{}字面值來建立對象,對象的屬性名稱可以為加''的字串,也可不加引號。這對JS來說沒有區別,訪問對象的屬性時,可以使用句點也可使用關聯陣列['name'],後者的好處是當我們不知道對象屬性名稱時,可以由變數來作為關聯陣列的索引。

3.2 建構函式

我們也可以通過自訂建構函式來產生對象,從而能執行個體化更多的對象。建構函式也是函數,我們需要用大寫的函數名即可。在函數中可以定義成員變數,成員函數等。

3.3 內容物件

在JS中,內容物件即this指標,即被調用函數所處的環境。其作用是在函數內部引用到調用它的對象本身。this的出現會之前介紹的靜態範圍產生影響,加入了動態內容。


由例子可以看到,我們可以通過不同的變數引用函數,不同之處調用上下文。

傳遞與綁定上下文

JavaScript的函數可以通過Call和Apply來動態綁定到特定的上下文。

如果想永久的綁定上下文,可以使用bind函數,需要注意的是同一函數上的多次bind是沒有效果的。

var person = function(){  name:'noname',   getName:function(){console.log(this.name); }};var bill = {name:'Bill'};person.getName(); //nonamebill.getName = person.getName;bill.getName();         //Billname = 'JavaScript';func = person.getName;func();         //JavaScript

3.4 原型

建立對象時,我們應該在建構函式內定義一般成員,而是其原型定義成員函數。

下面我們會主要介紹原型鏈

JS中有兩個特殊的對象:Object與Function,它們都是建構函式,用於產生對象。

Object.prototype是所有對象的祖先,Function.prototype是所有函數的原型,包括建構函式。

可以將JS的對象分為三類:使用者建立對象,建構函式對象,原型對象。

所有對象中都有一個__proto__屬性,其指向此對象的原型。

建構函式對象有prototype,指向其原型對象,通過此建構函式建立對象時,新建立對象的__proto__屬性將會指向建構函式的prototype屬性。

原型對象有一個constructor屬性,指向它對應的建構函式。

function Foo() {}
var obj = new Object();
var foo = new Foo();


參考文獻:《Node.JS開發指南》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.