创建对象
工厂模式
用函数封装创建特定对象的细节
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; }var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor"); person1.sayName(); //"Nicholas" person2.sayName(); //"Greg"
优点:对创建对象的细节进行封装,方便创建多个相似对象
缺点:同一个工厂创建的对象间没有联系;未解决对象识别问题。构造函数模式
利用构造函数创建对象,不用显式创建对象。new 操作符使得this绑定在新对象上,并且可以用instanceof操作符判断对象的来源。
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.sayName(); //"Nicholas" person2.sayName(); //"Greg" alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true alert(person2 instanceof Object); //true alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true alert(person2.constructor == Person); //true alert(person1.sayName == person2.sayName); //false
优点:解决了对象识别问题
缺点:每个方法要在每个实例上创建一遍原型模式
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); person1.sayName(); //"Nicholas" var person2 = new Person(); person2.sayName(); //"Nicholas" alert(person1.sayName == person2.sayName); //true alert(Person.prototype.isPrototypeOf(person1)); //true alert(Person.prototype.isPrototypeOf(person2)); //true //only works if Object.getPrototypeOf() is available if (Object.getPrototypeOf){ alert(Object.getPrototypeOf(person1) == Person.prototype); //true alert(Object.getPrototypeOf(person1).name); //"Nicholas" }
优点:实例之间共享原型的属性和方法
缺点:以对象字面量方法重写原型对象会切断之前所创建的对象与构造函数的联系;对象字面量重写原型时需加上constructor属性。 注意:1.对对象某属性进行赋值以外的操作时会发生标识符解析,若该属性只存在于原型中且为引用,操作将改变引用指向的对象。如下: function Person(){} Person.prototype.name = ["Nicola"]; Person.prototype.age = 18; var person1 = new Person(); var person2 = new Person(); person1.name.push("Alice"); console.log(person1.name);//["Nicola","Alice"] console.log(person2.name);//["Nicola","Alice"] 而如果是赋值操作,则不能改写原型中的值,而是新增一个该对象的同名属性。如下: function Person(){} Person.prototype.name = ["Nicola"]; Person.prototype.age = 18; var person1 = new Person(); var person2 = new Person(); person1.name = ["Alice"]; console.log(person1.name);//["Alice"] console.log(person2.name);//["Nicola"] delete person1.name; console.log(person1.name);//["Nicola"] 2.可通过hasOwnProperty方法判断某属性属于对象自己还是原型。 3.最好不要给原生对象添加原型方法。组合使用构造函数和原型
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype = { constructor: Person, sayName : function () { alert(this.name); } }; var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true
动态原型模式
把所有信息封装到构造函数中,在构造函数中初始化原型,是一种让有其它OO语言经验的开发人员更方便的语法糖。
function Person(name, age, job){//properties this.name = name; this.age = age; this.job = job; //methods if (typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; } } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName();
优点:方便有其它OO语言经验的开发人员上手。
缺点:同组合模式。寄生构造函数模式
本质是工厂模式,只不过通过new操作符调用函数。。主要用来扩展原生对象,其实还是语法糖。
function SpecialArray(){//create the array var values = new Array(); //add the values values.push.apply(values, arguments); //assign the method values.toPipedString = function(){ return this.join("|"); }; //return it return values; } var colors = new SpecialArray("red", "blue", "green"); alert(colors.toPipedString()); //"red|blue|green" alert(colors instanceof SpecialArray);
优点:可以像使用原生构造函数一样使用特殊构造函数创建经过扩展后的新对象,并不会影响到原生对象。
缺点:同工厂模式。稳妥构造函数模式
实例方法不引用this,不使用new调用构造函数。
function Person(name, age, job){ var o = new Object(); o.sayName = function(){ alert(name); }; return o; }var person1 = Person("Nicholas", 29, "Software Engineer"); person1.sayName(); //"Nicholas"
优点:除了特定方法没有其它访问构造函数传入参数的途径。
缺点:同工厂模式。