一、对象表示方法
1、普通对象
var person=new Object();
person.name="Nicholas";
person.age=19;
person.jog="Software Engineer,";
person.sayName=function(){
alert(this.name);
}
2、对象字面量
var person={
name:"Nicholas";
age:19;
job:"Software Enginner";
sayName:function(){alert(this.name)};
}
二、创建对象
工厂模式
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",19,"SoftEngineer");
var person2=createPerson("Greg",17,"Doctor");
工厂模式:根据外界给定的原料,生产出不同的类型的相应的产品、对象。工厂类负责创建的对象较少,客户指知道传入工厂类的参数,
对于如何创建对象(逻辑)不关心。解决了创建多个相似对象的问题。
工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。
构造函数模式
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){ //等于new Function(){} ,不同实例上的同名函数是不相等的
alert(this.name);
}
}
var Person1=new Person("Nicholas",19,"SoftEngineer");
var Person2=new Person("Greg",17,"Doctor"); //Person1和Person2分别保存着Person的一个不同的实例,这两个对象的constructor属性都指向Person
alert(Person1.constructor==Person); //true
alert(Person2.constructor==Person); //true
Person中的代码
①没有显示的创建对象;
②直接将属性和方法赋给了this对象;
③没有return语句。
按照惯例,构造函数首字母大写,非构造函数首字母小写。
创建自定义的构造函数意味着可以将它的实例作为一种特定的类型,这是构造函数模式胜过工厂模式的地方。
构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。
我们将sayName设置成全局函数
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}<pre name="code" class="javascript">Person.sayName=function(){ //等于new Function(){} ,不同实例上的同名函数是不相等的
alert(this.name);
}
var Person1=new Person("Nicholas",19,"SoftEngineer");var Person2=new Person("Greg",17,"Doctor"); //Person1和Person2分别保存着Person的一个不同的实例,这两个对象的constructor属性都指向Personalert(Person1.constructor==Person); //truealert(Person2.constructor==Person); //true
可是问题又来了,在全局作用域中定义了一个实际指向让Person使用的函数,在全局作用域中定义许多仅供特定对象使用的方法,浪费空间而且失去了面向对象的封装性。因此可以通过原型来解决这个问题。
原型模式
function Person(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=19';
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
原型函数省略了构造函数传递初始化参数这一环节,结果所有实例在默认情况下都取得了相同的属性值。原型模式的最大问题在于共享的本性,由于共享,因此如果一个实例修改了引用,另一个也随之更改了引用。因此我们通常不单独使用原型。
虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中创建一个与实例原型相同名称的属性,则会将原型中的同名属性屏蔽。
重写原型对象会切断现有原型与之前已经存在的对象实例之间的联系,它们引用的仍然是最初的原型。
组合使用构造函数模式和原型模式(重点)
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);
alert(person2.friends);
alert(person1.friends==person2.friends); //false
alert(person1.sayName==person2.sayName); //true
混合模式中构造函数适用于定义实例属性,而原型模式用于定义方法和共享属性。每个实例都会有自己的一份实例属性,但同时又共享着方法,最大限度的节省了内存。另外这种模式还支持传递初始参数。
动态原型模式
function person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
if(typeof this.sayName!="function"){
person.prototype.sayName=function(){
console.log(this.name);
}
}
}
var friend=new person("Nicholas",28,"Software Engineer");
friend.sayName();
这段代码只会在初次调用构造函数时执行。此后,原型已经完成初始化,不需要再做什么修改了。使用动态原型模式时,不能使用对象字面量重写原型。在已经创建了实例的情况下重写原型,就会切断现有实例与新原型之间的联系。
寄生构造函数模式
function Person(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 friend=new Person("Nicholas",28,"Software Engineer");
friend.sayName(); //"Nicholas"
这个模式可以在特殊的情况下来用来为对象创建构造函数。(good)
funtion specialArray(){
var values=new Array();
values.push.apply(values,arguments);
values.toPipedString=function(){
return this.join("|");
}
}
var colors=new specialArray("red","blue","green");
alert(colors.toPipedString());
在使用其他模式的情况下,不要使用这种模式。
稳妥构造函数模式
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。
稳妥构造函数模式与工厂模式的区别:
//稳妥构造函数
function person(name,age,sex){
var o=new Object();
o.name=name;
o.age=age;
o.sex=sex;
o.sayName=function(){
console.log(name);
}
return o;
}
var girl=person("zsn",18,"F");
girl.sayName();//zsn
girl.name="hello world";
girl.sayName();//zsn
console.log(girl.name); //hello world
// 工厂模式
function person(name,age,sex){
var o=new Object();
o.name=name;
o.age=age;
o.sex=sex;
o.sayName=function(){
console.log(this.name);
}
return o;
}
var girl=person("zsn",18,"F");
girl.sayName();//zsn
girl.name="hello world";
girl.sayName();//hello world
console.log(girl.name); //hello world
区别就是工厂模式有this,稳妥构造函数没有this。结果呢,工厂函数的sayName方法调用的值会改变。
三、继承
PS:
1、以new 操作符调用构造函数会经历一下四个步骤:
创建一个新的对象;
将构造函数的作用域赋给新的对象(因此this就指向了这个新对象);
执行构造函数中的代码;
返回新对象。