javascript做用域、閉包、對象與原型鏈

原文做者總結得特別好,本身收藏一下。^-^編程

1.做用域
1.1函數做用域
JS的在函數中定義的局部變量只對這個函數內部可見,稱之謂函數做用域。它沒有塊級做用域(所以if、for等語句中的花括號不是獨立做用域)數組

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

嵌套做用域變量的查找規則:
當前函數中引用一個變量時,js會搜索當前函數做用域,若是沒找到則搜索其上層做用域,直至全局做用域。閉包

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

 


詞法做用域規則:
函數的嵌套關係是定義時決定的,而非調用時決定的,即語法做用域,即嵌套關係是由詞法分析時肯定的,而非運行時決定。編程語言

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

 

所以,根據這兩個規則的相互做用,函數內不管什麼位置定義的局部變量,在進入函數時都是已經定義的,但未初始化,即爲undefined,直到運行到變量被賦值時才被初始化,所以如果訪問了未初始化的變量,咱們會獲得undefined的說明。函數式編程

1.2全局做用域
全局做用域的變量時全局對象的屬性,不論什麼函數中均可以直接訪問,而不須要經過全局對象,但加上全局對象,能夠提升搜索效率。
知足下列條件的變量屬於全局做用域:
在最外層定義的變量、全局對象的屬性、任何地方隱匿定義的變量。函數

2.閉包
2.1裝飾的定義this

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

 

在相似C/C++這種的非函數式編程語言中,咱們也能夠定義函數指針並返回,但外層函數在執行結束後爲內層函數定義的上下文信息會被銷燬,而在閉包中,則保存了返回的函數,還包含返回函數的上下文信息。(由詞法做用域所支持)並且在返回閉包以後,上下文信息即被單首創建出來,從而能夠生成多個互相獨立的閉包實例。spa

2.2閉包的用途
閉包有兩個用途,一是實現嵌套的回調函數,二是隱藏對象的細節。
對於前者,NodeJS的編程風格已經能夠說明問題,對於後者,函數內部的局部變量外部是不可見的,但能夠提供訪問函數來訪問和修改相應的局部變量,從而實現OO封裝的意圖。.net

3.對象
在基於類型的語言中,對象是由類實例化,而JS是基於原型的系統,對象是由原型複製生成的。
3.1 對象的建立與訪問prototype

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

3.2 構造函數

咱們也能夠經過自定義構造函數來生成對象,從而能實例化更多的對象。構造函數也是函數,咱們須要用大寫的函數名便可。在函數中能夠定義成員變量,成員函數等。

3.3 上下文對象

在JS中,上下文對象即this指針,即被調用函數所處的環境。其做用是在函數內部引用到調用它的對象自己。this的出現會以前介紹的靜態做用域產生影響,加入了動態的內容。

由例子能夠看到,咱們能夠經過不一樣的變量引用函數,不一樣之處調用上下文。

傳遞與綁定上下文

JavaScript的函數能夠經過Call和Apply來動態綁定到特定的上下文。

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

var person = { 
name:'noname', 
getName:function(){console.log(this.name); } 
}; 

var bill = {name:'Bill'}; 
person.getName(); //noname 
bill.getName = person.getName; 
bill.getName(); //Bill 
name = '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();

 

原文地址:http://blog.csdn.net/zzulp/article/details/8144520

相關文章
相關標籤/搜索