天天看點

《Javascript進階程式設計》閱讀筆記 ----第7章

文章目錄

    • 函數執行環境和作用域鍊
    • 關于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);
			}	
		}
		
	}
}
           

繼續閱讀