
JavaScript 語言核心(14)隱藏諸多細節的建構式
JavaScript 語言核心(13)在 Scope chain 查找變數 << 前情 如果你有以下建立物件的需求: function toString() { return '[' + this.name + ',' + this.age + ']'; } var p1 = { name : 'Justin', age : 35, toString : toString }; var p2 = { name : 'Monica', age : 32, toString : toString }; var p3 = { name : 'Irene', age : 2, toString : toString }; console.log(p1.toString()); // [Justin,35] console.log(p2.toString()); // [Monica,32] console.log(p3.toString()); // [Irene,2] 這些物件在建立時,具有相同的特性名稱,只不過特性值不同,其實你如下定義 function toString() { return '[' + this.name + ',' + this.age + ']'; } function Person(name, age) { this.name = name; this.age = age; this.toString = toString; } var p1 = new Person('Justin', 35); var p2 = new Person('Monica', 32); var p3 = new Person('Irene', 2); 接著如下呼叫 var p1 = new Person('Justin', 35); var p2 = new Person('Monica', 32); var p3 = new Person('Irene', 2); console.log(p1.toString()); // [Justin,35] console.log(p2.toString()); // [Monica,32] console.log(p3.toString()); // [Irene,2] 像 實際上使用 function toString() { return '[' + this.name + ',' + this.age + ']'; } function Person(name, age) { this.name = name; this.age = age; this.toString = toString; } var p = {}; Person.call(p, 'Justin', 35); console.log(p.toString()); // [Justin,35] 這也說明了,為什麼使用 說是一部份作了這些動作,不過還有別的細節,像是原型繼承以及 function toString() { return '[' + this.name + ',' + this.age + ']'; } function person(name, age) { return { name : name, age : age, toString : toString }; } var p = person('Justin', 35); console.log(p.toString()); // [Justin,35] 原型繼承會在另一篇文章中說明,稍後則就會看到 一個函式作為建構式使用時,基本上無需撰寫 function Nobody() { } function Person(name, age) { return []; } var n = new Nobody(); var p = new Person(); console.log(n instanceof Nobody); // true console.log(p instanceof Person); // false console.log(p instanceof Array); // true
每個透過 function Person() {} var p = new Person(); console.log(p.constructor == Person); // true 雖然這可以作為判斷物件類型的參考依據之一,不過要注意的是, 由於透過建構式所建立的物件,所有的特性都是直接新增在物件上,也因此可以直接透過 . 運算子加以存取。例如: function Person(name, age) { this.name = name; this.age = age; } var p = new Person('Justin', 35); console.log(p.name); // Justin console.log(p.age); // 35 對熟悉物件導向私有(private)特性的人來說,可能覺得這不安全,這相當於在物件導向觀念中,每個類別成員都是公開成員的意味。JavaScript 本身並沒有支援物件導向私用特性的語法,如果你想模擬,則可以如下: function Person(name, age) { this.getName = function() { return name; }; this.age = age; } var p = new Person('Justin', 35); console.log(p.name); // undefined console.log(p.getName()); // Justin console.log(p.age); // 35 以上假設的是, 由於 Closure 綁定的是變數本身,所以也可以如下,在設定值(或取得值)時予以保護: function Account() { var balance = 0; this.getBalance = function() { return balance; }; this.setBalance = function(money) { if(money < 0) { throw new Error('can\'t set negative balance.'); } balance = money; }; } var acct = new Account(); console.log(acct.getBalance()); // 0 acct.setBalance(1000); console.log(acct.getBalance()); // 1000 acct.setBalance(-1000); // Error: can't set negative balance 建構式還有一些細節需要瞭解,這會在下一篇文章中繼續討論。 |