ECMAScript 對象作用域

2018-09-21 17:07 更新

作用域指的是變量的適用范圍。

公用、私有和受保護(hù)作用域

概念

在傳統(tǒng)的面向?qū)ο蟪绦蛟O(shè)計中,主要關(guān)注于公用和私有作用域。公用作用域中的對象屬性可以從對象外部訪問,即開發(fā)者創(chuàng)建對象的實例后,就可使用它的公用屬性。而私有作用域中的屬性只能在對象內(nèi)部訪問,即對于外部世界來說,這些屬性并不存在。這意味著如果類定義了私有屬性和方法,則它的子類也不能訪問這些屬性和方法。

受保護(hù)作用域也是用于定義私有的屬性和方法,只是這些屬性和方法還能被其子類訪問。

ECMAScript 只有公用作用域

對 ECMAScript 討論上面這些作用域幾乎毫無意義,因為 ECMAScript 中只存在一種作用域 - 公用作用域。ECMAScript 中的所有對象的所有屬性和方法都是公用的。因此,定義自己的類和對象時,必須格外小心。記住,所有屬性和方法默認(rèn)都是公用的!

建議性的解決方法

許多開發(fā)者都在網(wǎng)上提出了有效的屬性作用域模式,解決了 ECMAScript 的這種問題。

由于缺少私有作用域,開發(fā)者確定了一個規(guī)約,說明哪些屬性和方法應(yīng)該被看做私有的。這種規(guī)約規(guī)定在屬性前后加下劃線:

obj._color_ = "blue";

這段代碼中,屬性 color 是私有的。注意,下劃線并不改變屬性是公用屬性的事實,它只是告訴其他開發(fā)者,應(yīng)該把該屬性看作私有的。

有些開發(fā)者還喜歡用單下劃線說明私有成員,例如:obj._color。

靜態(tài)作用域

靜態(tài)作用域定義的屬性和方法任何時候都能從同一位置訪問。在 Java 中,類可具有屬性和方法,無需實例化該類的對象,即可訪問這些屬性和方法,例如 java.net.URLEncoder 類,它的函數(shù) encode() 就是靜態(tài)方法。

ECMAScript 沒有靜態(tài)作用域

嚴(yán)格來說,ECMAScript 并沒有靜態(tài)作用域。不過,它可以給構(gòu)造函數(shù)提供屬性和方法。還記得嗎,構(gòu)造函數(shù)只是函數(shù)。函數(shù)是對象,對象可以有屬性和方法。例如:

function sayHello() {
  alert("hello");
}

sayHello.alternate = function() {
  alert("hi");
}

sayHello();		//輸出 "hello"
sayHello.alternate();	//輸出 "hi"

TIY

這里,方法 alternate() 實際上是函數(shù) sayHello 的方法??梢韵裾{(diào)用常規(guī)函數(shù)一樣調(diào)用 sayHello() 輸出 "hello",也可以調(diào)用 sayHello.alternate() 輸出 "hi"。即使如此,alternate() 也是 sayHello() 公用作用域中的方法,而不是靜態(tài)方法。

關(guān)鍵字 this

this 的功能

在 ECMAScript 中,要掌握的最重要的概念之一是關(guān)鍵字 this 的用法,它用在對象的方法中。關(guān)鍵字 this 總是指向調(diào)用該方法的對象,例如:

var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {
  alert(this.color);
};

oCar.showColor();		//輸出 "red"

TIY

在上面的代碼中,關(guān)鍵字 this 用在對象的 showColor() 方法中。在此環(huán)境中,this 等于 oCar。下面的代碼與上面的代碼的功能相同:

var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {
  alert(oCar.color);
};

oCar.showColor();		//輸出 "red"

TIY

使用 this 的原因

為什么使用 this 呢?因為在實例化對象時,總是不能確定開發(fā)者會使用什么樣的變量名。使用 this,即可在任何多個地方重用同一個函數(shù)。請思考下面的例子:

function showColor() {
  alert(this.color);
};

var oCar1 = new Object;
oCar1.color = "red";
oCar1.showColor = showColor;

var oCar2 = new Object;
oCar2.color = "blue";
oCar2.showColor = showColor;

oCar1.showColor();		//輸出 "red"
oCar2.showColor();		//輸出 "blue"

TIY

在上面的代碼中,首先用 this 定義函數(shù) showColor(),然后創(chuàng)建兩個對象(oCar1 和 oCar2),一個對象的 color 屬性被設(shè)置為 "red",另一個對象的 color 屬性被設(shè)置為 "blue"。兩個對象都被賦予了屬性 showColor,指向原始的 showColor () 函數(shù)(注意這里不存在命名問題,因為一個是全局函數(shù),而另一個是對象的屬性)。調(diào)用每個對象的 showColor(),oCar1 輸出是 "red",而 oCar2 的輸出是 "blue"。這是因為調(diào)用 oCar1.showColor() 時,函數(shù)中的 this 關(guān)鍵字等于 oCar1。調(diào)用 oCar2.showColor() 時,函數(shù)中的 this 關(guān)鍵字等于 oCar2。

注意,引用對象的屬性時,必須使用 this 關(guān)鍵字。例如,如果采用下面的代碼,showColor() 方法不能運行:

function showColor() {
  alert(color);
};

如果不用對象或 this 關(guān)鍵字引用變量,ECMAScript 就會把它看作局部變量或全局變量。然后該函數(shù)將查找名為 color 的局部或全局變量,但是不會找到。結(jié)果如何呢?該函數(shù)將在警告中顯示 "null"。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號