在Javascript中,除了幾種原始類型外,其他皆爲對象(Object,Array ...),既然對象如此重要,那就列舉一下在Javascript中如何建立對象:javascript
var person = new Object(); person.name = 'krew'; person.age = 26;
對象字面量是對象定義的一種簡寫形式,目的在於簡化建立包含大量屬性的對象的過程。java
var person = { name : 'krew', age : 26 }
工廠模式是一種設計模式,經過對建立具體對象的過程進行抽象。使用函數來封裝建立對象的細節,能夠無數次地調用用該函數,每次均可以獲得包含制定內容的對象。設計模式
function personFactory(name, age){ var obj = new Object(); obj.name = name; obj.age = age; obj.sayName = function(){ console.log(this.name); } return obj; } var person1 = personFactory('krew', 26); var person2 = personFactory('john', 20);
基於工廠模式建立對象雖然方便,可是建立出來的對象沒有特定的對象類型(好比原生對象Object, Array的實例都有本身的類型),因此就採用構造函數模式來建立對象,就能解決識別對象類型的問題。數組
function Person(name, age){ this.name = name; this.age = age; this.sayName = function() { console.log(this.name); } } var person1 = new Person('krew', 26); var person2 = new Person('john', 20); person1.sayName(); // 'krew' person2.sayName(); // 'john' person1.constructor == Person // true person2.constructor == Person // true
每一個函數在建立的時候,就會根據特定的規則爲該函數建立一個prototype
屬性,這個屬性是指向函數的原型對象的指針。這個原型對象的包含能夠由特定類型的全部實例共享的屬性和方法。因此,在構造函數的prototype
屬性上添加屬性與方法,該構造函數的全部實例都會在原型鏈上查找到這些屬性與方法。函數
function Person() { } Person.prototype.name = 'krew'; Person.prototype.age = 26; Person.prototype.sayName = function() { console.log(this.name); } var person1 = new Person(); var person2 = new Person(); person1.sayName(); // 'krew' person2.sayName(); // 'krew'
因爲原型對象中的屬性是被不少實例所共享的,對於引用類型的屬性值,將會存在實例間沒法隔離的問題:this
function Person() { } Person.prototype = { constructor : Person, name : 'krew', age : 26, friends : ['john', 'kitty'], showFriends : function() { console.log(this.friends); } } var person1 = new Person(); var person2 = new Person(); person1.friends.push('petter'); person1.showFriends() // ['john', 'kitty', 'petter'] person2.showFriends() // ['john', 'kitty', 'petter']
能夠看到,僅是在實例person1的friends屬性上添加值,但person2也跟着變化。這是由於friends數組存在於Person.prototype而非person1中,person1與person2中的friends皆爲引用Person.prototype中的friends,因此當經過person1來改變friends的時候,person2中的friends也會反映出來。
經過組合構造函數與原型模式能夠解決上面出現的問題,構造函數模式用於定義實例屬性,而原型模式用於定義方法和共享的屬性,每一個實例會有本身的一份實例屬性,同時又共享着方法的引用,極大的節省了內存。prototype
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayName = function() { console.log(this.name); } var person1 = new Person('krew', 26); var person2 = new Person('john', 20); person1.sayName(); // 'krew' person2.sayName(); // 'john'
function Person(name, age){ this.name = name; this.age = age; if (typeof this.sayName != 'function') { Person.prototype.sayName = function() { console.log(this.name); } } } var person1 = new Person('krew', 26); var person2 = new Person('john', 20); person1.sayName(); // 'krew' person2.sayName(); // 'john'
function Person(name, age) { var obj = new Object(); obj.name = name; obj.age = age; obj.sayName = function() { console.log(this.name); } return obj; } var person1 = new Person('krew', 26); var person2 = new Person('john', 20); person1.sayName(); // 'krew' person2.sayName(); // 'john'
function Person(name) { var obj = new Object(); obj.sayName = function() { console.log(name); } return obj; } var person1 = Person('krew'); var person2 = Person('john'); person1.sayName(); // 'krew' person2.sayName(); // 'john'