通过创建一个Object实例
var person = new Object(); person.name = "zhouquan"; person.age = 21; person.sayName = function(){ console.log(this.name); }; person.sayName();//zhouquan
对象字面量方式
var person = { name: "zhouquan", age: 21, sayName:function(){ console.log(this.name); } }; person.sayName();//zhouquan
通过普通的创建object实例的方式和对象字面量的方式创建对象的方式的缺点在于:这两种方式都不适合多次创建同一类型的对象。
工厂模式
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ console.log(this.name); }; return o; } var person1 = createPerson("zhouquan", 22, "student"); person1.sayName(); //zhouquan var person2 = createPerson("zhouquan2", 23, "Programer"); person2.sayName(); //zhouquan2
函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象。可以无数次的调用这个函数,而每次都会返回一个包含数个属性的和一个方法的对象。工厂模式虽然解决的创建多个类似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。
构造函数模式
function Person(name, age){ this.name = name; this.age = age; this.sayName = function(){ console.log(this.name); }; } var person1 = new Person("zhouquan", 21); person1.sayName(); //zhouquan var person2 = new Person("zhouquan2", 23); person2.sayName(); //zhouquan2
用这种方式创建对象更工厂模式比起来具有以下几点区别:
- 没有显示的创建对象
- 直接将属性和方法赋给了this对象
- 没有return语句
此外,还应该注意到函数名Person使用的大写字母P。这个是为了区别于其他的函数。
原型模式
function Person(){ } Person.prototype.name = "zhouquan"; Person.prototype.age = 21; Person.prototype.sayName = function(){ console.log(this.name); }; var person1 = new Person(); person1.sayName();//zhouquan var person2 = new Person(); person2.sayName();//zhouquan
prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以有特定类型的所有实例共享的属性和方法。使用原型对象的好处也就是可以让所有的对象实例共享它所包含的属性和方法。
但是这种方法写起来还是不方便,需要在每一个属性或者方法前面书写Person.prototype,我可以结合前面的对象字面量的方法来进行改进:
function Person(){ } Person.prototype={ name : "zhouquan", age : 21, sayName : function(){ console.log(this.name); } }; var person1 = new Person(); person1.sayName();//zhouquan var person2 = new Person(); person2.sayName();//zhouquan
组合使用构造函数模式和原型模式
function Person(name, age){ this.name = name; this.age = age; } Person.prototype={ sayName : function(){ console.log(this.name); } }; var person1 = new Person("zhouquan", 21); person1.sayName();//zhouquan var person2 = new Person("xiaozhou", 21); person2.sayName();//xiaozhou
这种方式是创建自定义类型的最常见方式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。这样,每个实例都会有自己的一份实例属性的副本,但同时又共享这对方法的引用,最大限度地节省了内存。另外,这种组合模式还支持向构造函数传递参数。可以说,这是用来定义引用类型的一中默认模式。
动态原型模式
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("zhouquan", 21); person1.sayName();//zhouquan var person2 = new Person("xiaozhou", 21); person2.sayName();//xiaozhou
这里只在sayName()方法不存在的情况下,才会将它添加到原型中,if语句只在初次调用函数时才会执行。其中if语句检查的可以是初始化之后应该存在的任何属性或方法,不必用一大堆if语句检查每个属性和方法,只要检查一个即可。需要注意的是,使用动态原型模式时,不能使用对象字面量重写原型,因为如果在以及创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。