摘自http://libinwalan.iteye.com/blog/153344
關鍵字: javascript對象, 面向對象
看js高級程序一書,記錄對自己比較重要的。
面嚮對象語言的要求:
1.封裝 2.聚集 3.繼承 4.多態
1.在Javascript中 可以創建並且使用的對象有三種
(1)本地對象 比如:Array Date and so on。
(2)內置對象 比如:Global Math(每個內置對象都是本地對象)
(3)宿主對象 定義:所有非本地對象都是宿主對象。所以所有的BOM(瀏覽器對象模型)和DOM(文檔對象模型)都是宿主對象。
2.作用域
(1)關鍵字this:總是指向調用該方法的對象 例如:
- var oCar = new Object;
- oCar.color="red";
- oCar .showColor = function(){
- alert(this.color);//outputs "red"
- };
- //在上面的環境中 this等於car,下面的代碼與上面的代碼意義相同
- var oCar = new Object;
- oCar.color="red";
- oCar .showColor = function(){
- alert(oCar.color);//outputs "red"
- };
var oCar = new Object; oCar.color="red"; oCar .showColor = function(){ alert(this.color);//outputs "red" }; //在上面的環境中 this等於car,下面的代碼與上面的代碼意義相同 var oCar = new Object; oCar.color="red"; oCar .showColor = function(){ alert(oCar.color);//outputs "red" };
使用this的好處是:可以在任意多個地方重用同一個函數。
3.定義類或對象
(1)工廠方式:考慮下面的代碼
- <script type="text/javascript">
- function createCar(color, doors, mpg) {
- var tempcar = new Object;
- tempcar.color = color;
- tempcar.doors = doors;
- tempcar.mpg = mpg;
- tempcar.showColor = function () {
- alert(this.color)
- };
- return tempcar;
- }
- var car1 = createCar("red", 4, 23);
- var car2 = createCar("blue", 3, 25);
- car1.showColor(); //outputs "red"
- car2.showColor(); //outputs "blue"
- </script>
<script type="text/javascript"> function createCar(color, doors, mpg) { var tempcar = new Object; tempcar.color = color; tempcar.doors = doors; tempcar.mpg = mpg; tempcar.showColor = function () { alert(this.color) }; return tempcar; } var car1 = createCar("red", 4, 23); var car2 = createCar("blue", 3, 25); car1.showColor(); //outputs "red" car2.showColor(); //outputs "blue" </script>
代碼夠清楚吧 不用多說了,但是要看清楚上面的代碼產生的問題:每次調用函數createCar(),都要創建新函數showColor();這意味着每個對象都有自己的showColor()版本,而事實上每個對象都共享了同一個函數。
所有這些問題引發了構造函數方式的出現:考慮下面代碼
- <script type="text/javascript">
- function Car(sColor, iDoors, iMpg) {
- this.color = sColor;
- this.doors = iDoors;
- this.mpg = iMpg;
- this.showColor = function () {
- alert(this.color)
- };
- }
- var oCar1 = new Car("red", 4, 23);
- var oCar2 = new Car("blue", 3, 25);
- oCar1.showColor(); //outputs "red"
- oCar2.showColor(); //outputs "blue"
- </script>
<script type="text/javascript"> function Car(sColor, iDoors, iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.showColor = function () { alert(this.color) }; } var oCar1 = new Car("red", 4, 23); var oCar2 = new Car("blue", 3, 25); oCar1.showColor(); //outputs "red" oCar2.showColor(); //outputs "blue" </script>
你可能已經注意到差別了,在構造函數內部無創建對象,而是使用this關鍵字。現在就更像創建一般對象了。但是可惜它的缺陷和工廠函數的缺陷一樣。
(2)原型方式:即利用prototype屬性
首先讓我們看下面的例子:
- <script type="text/javascript">
- function Car() {
- }
- Car.prototype.color = "red";
- Car.prototype.doors = 4;
- Car.prototype.mpg = 23;
- Car.prototype.showColor = function () {
- alert(this.color);
- };
- var oCar1 = new Car();
- var oCar2 = new Car();
- </script>
<script type="text/javascript"> function Car() { } Car.prototype.color = "red"; Car.prototype.doors = 4; Car.prototype.mpg = 23; Car.prototype.showColor = function () { alert(this.color); }; var oCar1 = new Car(); var oCar2 = new Car(); </script>
在上面的代碼中,通過給Car的pototype屬性添加屬性去定義Car對象的屬性。從語義上講,所有的屬性看起來都屬於一個對象,從而解決了前面方式存在的問題。但是遺憾的是它並不盡如人意。爲什麼呢?考慮下面的例子
- <script type="text/javascript">
- function Car() {
- }
- Car.prototype.color = "red";
- Car.prototype.doors = 4;
- Car.prototype.mpg = 23;
- Car.prototype.drivers = new Array("Mike", "Sue");
- Car.prototype.showColor = function () {
- alert(this.color);
- };
- var oCar1 = new Car();
- var oCar2 = new Car();
- oCar1.drivers.push("Matt");
- alert(oCar1.drivers); //outputs "Mike,Sue,Matt"
- alert(oCar2.drivers); //outputs "Mike,Sue,Matt"
- </script>
<script type="text/javascript"> function Car() { } Car.prototype.color = "red"; Car.prototype.doors = 4; Car.prototype.mpg = 23; Car.prototype.drivers = new Array("Mike", "Sue"); Car.prototype.showColor = function () { alert(this.color); }; var oCar1 = new Car(); var oCar2 = new Car(); oCar1.drivers.push("Matt"); alert(oCar1.drivers); //outputs "Mike,Sue,Matt" alert(oCar2.drivers); //outputs "Mike,Sue,Matt" </script>
看到了吧 這是因爲Car的兩個實例都指向同一個數組。所以輸出都一樣了。
那麼是否有一種合理的創建對象的方法呢?答案是需要聯合使用構造函數和原型方試 考慮下面的列子
- <script type="text/javascript">
- function Car(sColor, iDoors, iMpg) {
- this.color = sColor;
- this.doors = iDoors;
- this.mpg = iMpg;
- this.drivers = new Array("Mike", "Sue");
- }
- Car.prototype.showColor = function () {
- alert(this.color);
- };
- var oCar1 = new Car("red", 4, 23);
- var oCar2 = new Car("blue", 3, 25);
- oCar1.drivers.push("Matt");
- alert(oCar1.drivers); //outputs "Mike,Sue,Matt"
- alert(oCar2.drivers); //outputs "Mike,Sue"
- </script>
<script type="text/javascript"> function Car(sColor, iDoors, iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array("Mike", "Sue"); } Car.prototype.showColor = function () { alert(this.color); }; var oCar1 = new Car("red", 4, 23); var oCar2 = new Car("blue", 3, 25); oCar1.drivers.push("Matt"); alert(oCar1.drivers); //outputs "Mike,Sue,Matt" alert(oCar2.drivers); //outputs "Mike,Sue" </script>根據上面講述的內容 不難看出這種方式創建對象就更像創建一般對象了。這纔是最優的
(3)其他方法
包括動態原型法(和上面最優的方式其實差不多,不做介紹了) 和混合工廠方式(不推薦,不做介紹了)
4.採用哪種方式:不用多說 當然是最優的拉,給個例子。運行下就知道效率了
- <script type="text/javascript">
- function StringBuffer() {
- this.__strings__ = new Array;
- }
- StringBuffer.prototype.append = function (str) {
- this.__strings__.push(str);
- };
- StringBuffer.prototype.toString = function () {
- return this.__strings__.join("");
- };
- var d1 = new Date();
- var str = "";
- for (var i=0; i < 10000; i++) {
- str += "text";
- }
- var d2 = new Date();
- document.write("Concatenation with plus: " + (d2.getTime() - d1.getTime()) + " milliseconds");
- var buffer = new StringBuffer();
- d1 = new Date();
- for (var i=0; i < 10000; i++) {
- buffer.append("text");
- }
- var result = buffer.toString();
- d2 = new Date();
- document.write("<br />Concatenation with StringBuffer: " + (d2.getTime() -
<script type="text/javascript"> function StringBuffer() { this.__strings__ = new Array; } StringBuffer.prototype.append = function (str) { this.__strings__.push(str); }; StringBuffer.prototype.toString = function () { return this.__strings__.join(""); }; var d1 = new Date(); var str = ""; for (var i=0; i < 10000; i++) { str += "text"; } var d2 = new Date(); document.write("Concatenation with plus: " + (d2.getTime() - d1.getTime()) + " milliseconds"); var buffer = new StringBuffer(); d1 = new Date(); for (var i=0; i < 10000; i++) { buffer.append("text"); } var result = buffer.toString(); d2 = new Date(); document.write("<br />Concatenation with StringBuffer: " + (d2.getTime() -
- d1.getTime()) + " milliseconds");
- </script>
d1.getTime()) + " milliseconds"); </script>這段代碼對字符串鏈接進行2個測試,第一個使用加號,第二個使用StringBuffer類。事實證明後者比前者節省大量的時間。COOL! OVER!