在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'