文章目錄
-
- 函數執行環境和作用域鍊
- 關于this和that的問題
- 模仿塊級作用域
- 私有變量和公有方法
-
- 構造函數模式
- 靜态私有變量
- 子產品模式(單例模式)
函數執行環境和作用域鍊
要了解JavaScript,必須了解函數執行環境與作用域鍊(棧)!!
ES5以函數作為執行環境的劃分,代碼執行從外部到内部,執行環境從外部環境到内部環境依次堆棧,每個函數執行完畢,其執行環境對應的則出棧。
閉包:内部執行環境引用了外部執行環境中的變量,是以外部執行環境的變量不會被銷毀。
關于this和that的問題
函數調用時,會搜尋誰調用了這個函數。
var name = "The window";
var obj = {
name: "My obj",
getName: function(){
return function(){
return this.name;
}
}
}
alert(obj.getName()()); // "The window"
由于調用getName傳回的是匿名函數,匿名函數直接運作時,沒有人調用它,是以它的this指向window。
假如:
var obj = {
name: "My obj",
getName: function(){
return function(){
return this.name;
}
}
}
obj.test = obj.getName();
obj.test() // “My obj“
或者:
var obj = {
name: "My obj",
getName: function(){
var that = this;
return function(){
return that.name;
}
}
}
obj.getName()(); // "My obj"
模仿塊級作用域
由于JS沒有塊級作用域,而是以函數範圍作為作用域劃分。是以可以用以下方法模仿塊級作用域,使用匿名立即執行函數來建立塊級作用域。
(function(){
//這裡是塊級作用域
})()
由于JS将function關鍵字當作函數聲明的開始,是以不能直接在函數聲明後加
()
而是應該用
()
包住函數。
當在全局環境使用該方式時,可以建立自己的私有環境,避免向全局注入過多函數和變量。這在多人協作中很重要。
私有變量和公有方法
構造函數模式
由于函數内部的變量對于外部不可通路,是以可以使用函數來建立私有變量,使用閉包來建立公有方法
function MyObject() {
var privateVar = 20; // 私有變量
this.getName = function() { //公有方法
return privateVar;
};
this.setName = function(value) { //公有方法
privateVar = value;
};
}
注意,不能寫成以下函數:
function MyObject() {
this.privateVar = 20; // 公有變量
this.getName = function() { //公有方法
return this.privateVar;
};
this.setName = function(value) { //公有方法
this.privateVar = value;
};
}
隻要加上this,那麼變量就将成為構造函數構造出來的對象的一個可以通路的屬性。
這種方法的缺點在于,對于每一個變量都會建立一組相同的新方法。
靜态私有變量
建立一個所有執行個體共享的私有變量和公有方法
//立即執行函數建立私有域
(function(){
//靜态私有變量
var name = "";
//構造函數
//Person為全局變量友善外部通路
Person = function(value) {
name = value;
};
//所有執行個體的共享方法
Person.prototype.getName = function(){
return name;
};
Person.prototype.setName = function(){
name = value;
};
})();
子產品模式(單例模式)
例子:一個管理元件的application。
var application = function() {
//私有,單例變量
var components = new Array();
//初始化
components.push(new BaseComponent());
return {
//公有接口
getComponentCount: function() {
return components.length;
},
registerComponent: function(component) {
if (typeof component == "object") {
components.push(component);
}
}
}
}