// 以 function 為建構子 function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } //然後活化類別 var p = new Person("Dino", "Wang");
如你所見這樣的類別並不具有"成員函式",所以當你需要成員函式時你可能會手動繫結上去
// 附加一個匿名函式到 p 實體 p.fullName = function () { return this.firstName + " " + this.lastName; }
這樣的問題是,每一個被活化的類別都需要進行一次上述動作(以下稱為成員繫結),如果你這類別會產生多個物件,就會造成匿名函式重複產生的問題(浪費記憶體)
正確而有效的做法是進行 prototype 宣告,將類別定義修改如下
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } Person.prototype.fullName = function () { return this.firstName + " " + this.lastName; } var p = new Person("Dino", "Wang"); var fullName = p.fullName(); // Workable!此後每一個被活化的 Person 類別都自動具有 fullName 成員函式,不需要額外進行繫結
值得一提的是,javascript 允許你對已經定義過的類別,附加成員,還且還會一併讓已經被活化的物件也具有這份"原型",例如:
// 你可以為 String 擴充 trim() 功能 String.prototype.trim = function () { return this.replace(/^\s*|\s*$/g, ""); } var name = " Dino ".trim(); // 為 Array 增加 append() 以模擬出 .NET Framework 效率較高的 StringBuilder Array.prototype.append = function (val) { this.push(val); return this; } var sb = [].append("1").append("2").append("3").join(" ");
常用的 javascript 版本(1.2) 沒有常見的 class 的定義方式,因為它是 prototype-oriented
NOTE: 關於 javascript 對比到一般物件導向語言的 繼承、類別成員、靜態成員 的方式,簡單整理如下:
// Constructor function SuperClass() {} // SuperClass behaviors SuperClass.prototype.toString = function () { return "I'm super class."; } // Constructor function UserClass() { SuperClass.apply(this, arguments); // Call constructor, like C# base(...) } // Inheritance UserClass.prototype = new SuperClass; // Data member UserClass.prototype.property1 = 0; UserClass.prototype.property2 = 0; // Member function UserClass.prototype.method1 = function () {} UserClass.prototype.method2 = function () {} // Static data member UserClass.instances = 0; UserClass.cache = []; // Static member function UserClass.staticMethod1 = function () {} UserClass.staticMethod2 = function () {}
沒有留言:
張貼留言