JavaScript 中類的實現 (js中的對象)

原文地址:http://blog.chinaunix.net/uid-15223977-id-2774362.html

在js中利用new、this和prototype三個關鍵字可以實現完備的面向對象特徵。而創建一個新的對象new關鍵字是不可缺少的。


只用new創建一個最簡單的對象:(1)

var t = new Object;
t.= 'test'
;
t.= function (){alert(t.a)};
t.b();

彈出“test”

再利用new和this關鍵字改進:(2)

var t = new Object;
t.= 'test'
t.= function (){alert(this.a)};
t.b();

彈出“test”,但仍不能實現重複建立多個實例。

改進:(3)

function test()
{
    this.= 'test';
    this.= function (){alert(this.a)};
    return 1;
}
var t = test();
alert(a);
b();
alert(t);
alert(t.a);
t.b();

依次,彈出test、彈出test、彈出1、undefined、對象不支持此屬性或方法。可見,直接調用函數時,t只是函數的返回值,並不是需要的對象。由於test是由window對象調用的,this指代了window對象,把a和b賦給了window對象。

加上new:(4)

function test()
{
    this.= 'test';
    this.= function (){alert(this.a)};
    return 1;
}
var t = new test();
alert(t);
alert(t.a);
t.b();
alert(a);
b();

依次,彈出[object Object]、彈出test、彈出test、編譯錯誤'a'未定義、停止執行。可見,用new運算符時,調用test函數的對象被賦給了t,this指代t對象,函數返回值被忽略。a和b()在window上未定義。

也可以採用函數返回值的方式建立對象:(5)

function test()
{
    var t = new Object;
    t.= 'test';
    t.= function (){alert(this.a)};
    return t;
}
var t1 = test();
alert(t1);
alert(t1.a);
t1.b();
var
 t2 = test();
t2.a = 
'test2';
t2.b;

alert(Object.a);
Object.b();

以上依次,彈出[object Object]、彈出test、彈出test、彈出test2、彈出undefined、編譯錯誤:對象不支持此屬性或方法,停止執行。可見,在函數內部new操作符新建了個基本對象並返回,兩個test實例不相互影響,也不影響Object對象。

但是上面的4和5的例子都有個弊端就是b方法其實只是一個函數指針,兩個指針所指向的函數在調用構造函數時即時創建,並非爲同一個程序實例,造成存儲空間浪費。
一種改進方案是:(6)

var test_b = function (){alert(this.a)};
function test()
{
    var t = new Object;
    t.= 'test';
    t.= test_b;
    return t;
}
var t1 = test();
t1.b();
var t2 = test();
t2.= 'test2';
t2.b();

這樣兩個實例的b屬性爲同一個值test_b指針,都指向同一個函數。

除了這種方式還有一種辦法做到,那就是js內置於每個對象中的對象類型原型的引用prototype屬性。
用prototype屬性提供對象的類的一組基本功能,對象的新實例“繼承”賦予該對象原型的操作。
看示例:(7)

function test()
{
    this.= 'test';
}
test.prototype.= function (){alert(this.a)};
test.prototype.= new Array();

test.prototype.= 5;
var t1 = new test();
t1.b();
var t2 = new test();
t2.= 'test2';
t2.b();
//////
t1.= [1,2];

alert(t1.c);
t2.c[1] = 4;

alert(t2.c);
alert(t1.c);

//////

t2.= 6;
alert(t2.d);
alert(t1.d);

依次,彈出test、彈出test2、彈出1,2,彈出1,4,彈出1,2,彈出6,彈出5。可見,目的達到了,後面的示例說明:當prototype的屬性爲對象的引用時,它爲指向對象的指針,和普通變量一樣被每個實例繼承。另外,prototype屬性在對象被實例化前創建。也不可以放在函數內因爲那樣每次實例化對象時,都會爲prototype的屬性重新賦值,那樣仍然沒達到目地。


在看下js中的繼承:(8)

function test()
{
    this.= 'test';
    this.= function (){alert(this.a)};
}
function subTest()
{
    this.peraP = test;
    this.peraP();
    this.subName = 'subTest';
}
var t1 = new test();
t1.b();
var t2 = new subTest();
t2.b();
alert(t2.subName);

依次輸出:彈出test、彈出test、彈出subTest。在子類的構造函數內,用this調用父類構造函數,實現繼承。

當類的構造函數不需要傳遞參數時,也可以使用原型鏈實現繼承。
例:(9)

function test()
{
    this.= 'test';
}
test.prototype.= function (){alert(this.a)};

function subTest()
{
    this.subName = 'subTest';
}
subTest.prototype = new test;
subTest.prototype.showName = function (){alert(this.subName)};

var t1 = new test();
t1.b();
var t2 = new subTest();
t2.b();
t2.showName();

依次輸出:彈出test、彈出test、彈出subTest。當父類的構造函數不需要傳遞參數時,可以用subClass.prototype = new ParentClass;的方式覆蓋子類的prototype原型,子類的新原型屬性放在後面添加。



附錄:
new 運算符

new
 運算符執行下面的任務:
1、創建一個沒有成員的對象。
2、爲那個對象調用構造函數,傳遞一個指針給新創建的對象作爲 this 指針。
3、然後構造函數根據傳遞給它的參數初始化該對象。


this 語句

指當前對象。
this
.property
必選的 property 參數指的是對象的屬性。

說明
this 關鍵字通常在對象的構造函數中使用,用來引用對象。
對於 JScript 的客戶版本,如果在其他所有對象的上下文之外使用 
this,則它指的是 window 對象。


prototype 屬性

返回對象類型原型的引用。
objectName
.prototype
objectName 
參數是對象的名稱。

說明
用 prototype 屬性提供對象的類的一組基本功能。對象的新實例“繼承”賦予該對象原型的操作。所有 JScript 內部對象都有 prototype 屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章