创建对象的方式和继承的方式

来源:互联网 发布:js购物车功能怎么实现 编辑:程序博客网 时间:2024/05/07 14:08

1.使用object构造函数

var person=new Object();

person.name="Nicholas";

person.age=23;

person.job="Software Engineer";

person.sayName=function(){

alert(this.name);

}

2.使用对象字面量

var person={

name:"Nicholas";

age:23;

job:"Software Engineer";

sayName:function(){

alert(this.name);

}

}

由于方法1和方法2都可以用来创建单个对象,使用同一个接口创建很多对象,会产生大量的重复代码。

3.工厂模式

(用函数来封装以特定接口来创建对象)

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",23,"software Engineer");

var person2=createPerson("Greg",27,"Doctor");

4.构造函数模式

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",23,"Software Engineer");

var person2=new Person("Greg",22,"Doctor");

person1和person2都有一个名为sayName()的方法,但那两个方法不是同一个Function的实例。可以通过把函数定义转移到构造函数外部来解决这个问题

function  Person(name,age,job){

this.name=name;

this.age=age;

this.job=job;

this.sayName=sayName;

}

 function sayName(){

alert(this.name);

}

}

//此时person1和person2对象就共享了在全局作用域中定义的同一个sayName()函数

var person1=new Person("Nicholas",23,"Software Engineer");

var person2=new Person("Greg",22,"Doctor");

构造函数的缺点:由于this指针在对象实例的时候发生改变指向新的实例。这时新实例的方法也要重新创建,如果n个实例就要n次重建相同的方法。

5.原型模式

使用原型对象的好处就是让所有对象实例共享它所包含的属性和方法

function Person(){

}

Person.prototype.name="Nicholas";

Person.prototype.age=24;

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;

此时person1和person2访问的都是同一组属性和同一个sayName()函数

这种模式定义的对象,在调用方法的时候过程:调用person1.sayName();先看实例中有没有,有调之,无追踪到原型,有调之,无出错,调用失败。

理解原型对象:

只要创建了一个函数,该函数就会自动拥有一个prototype属性,而每一个prototype属性都会自动获得一个constructor属性;constructor属性有一个隐含的指针,该指针指向prototype属性所在的函数;

Person的每个实例都包含一个隐形指针,指向构造函数的原型对象Person.prototype;

方法:

可以通过原型对象.isPrototypeOf(实例对象)来判断实对象的原型是否为当前对象;

alert(Person.prototype.isPrototypeOf(person1)==Person.prototype);//true

可以使用Object.getPrototypeOf()可以方便的取得一个对象的原型的值;

alert(Object.getPrototypeOf(person1).name);//"Nicholas"

当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性。

可以使用hasOwnProperty()方法检测一个属性是否存在与实例中,还是存在于原型中。只在给定属性存在于对象实例中时,才会返回true;

利用in操作符可以判断属性是否存在于实例对象或者原型对象中

同时使用hasOwnProperty()方法和in操作符,就可以确定该属性到底存在于实例对象中还是原型对象中;

for-in循环,返回的是所有能够通过对象访问的、可枚举的属性,其中既包括存在于实例中的属性,也包括存在于原型中的属性。

通过Object.keys()方法可以取得对象上所有可枚举的实例属性;

如果想要得到所有实例属性,无论是否可枚举,都可以使用Object.getOwnPropertyNames()方法(不可枚举属性有constructor);

更简单的原型语法:通过对象字面量

function Person(){

}

Person.prototype={

name:"Nicholas";

age:22:

job:"Software Engineer";

sayName:function(){

alert(this.name);

}

};

6.组合使用构造函数和原型模式(最常见的方式)

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);

}

}

这种纯原型的模式问题也很明显,所有的属性,方法都是共享的,不能让对象具体化。常常我们想每个对象有自己的属性。于是,结合前两种,产生新的模式

7.动态原型模式

function  Person(name,age,job){

this.name=name;

this.age=age;

this.job="Software Engineer";

//方法

if(typeof this.sayName!="function"){//这里只有在sayName()方法不存在的情况下,才会将它添加到原型中

Person.prototype.sayName=function(){

alert(this.name);

};

}

}

var friend =new Person("Nicholas",22,"Software Engineer");

friend.sayName();

8.寄生构造函数模式(不常用)

寄生构造函数,其实就是工厂模式+构造函数模式。这种模式比较通用,但不能确定对象关系,所以,在可以使用之前所说的模式时,不建议使用此模式。在什么情况下使用寄生构造函数比较合适呢?假设要创建一个具有额外方法的引用类型

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",22,"Software Engineer");

fridend.sayName();//"Nicholas"

9.稳妥构造函数模式

在一些安全的环境中,比如禁止使用 this 和 new,这里的 this 是构造函数里不使用 this,这里的 new 是在外部实例化构造函数时不使用 new。这种创建方式叫做稳妥构造函数。

最适合在一些安全的环境中,或者在防止数据被其他应用程序改动时使用

function Person(name,age,job){

var o=new Object();

//定义私有变量和函数

var name="Nicholas";

var age=23;

 //添加方法

o.sayName=function(){

alert(name);

};

return o;

}


继承:

方式一:原型链

基本思想是:利用原型让一个引用类型继承另外一个引用类型的属性和方法。

举例代码:

function SuperType(){//定义一个父函数

this.protype=true;

}

SuperType.prototype.getSuperValue=function(){

return this.property;

}

function SubType(){//定义一个子函数

this.subproperty=false;

}

SubType.prototype=new SuperType();//继承了SuperType


subType.prototype.getSubValue=function(){

return this.subproperty;

}

var instance=new SubType();

alert(instance.getSubValue());//true

方式二:借用构造函数

基本思想:在子类型构造函数的内部调用超类型构造函数

如:

function SuperType(){

this.colors=["red", "green" ,"blue"];

}

function SubType(){

SuperType.call(this);//继承了SuperType

}

var instance1=new SubType();

instance1.colors.push("black");

alert(instance1.colors);//"red,green,blue,black"


var instance2=new SubType();

alert(instance2.colors);//"red,green,blue"

方式三:组合继承(最常用的继承方式)

指的是将原型链和借用构造函数的技术组合在一起,从而发挥二者之长;

基本思想:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承;这样,既通过在原型上的定义方法实现了函数复用,又能保证每个实例都有自己的属性。

如:

function SuperType(name){

this.name=name;

this.colors=["red","blue","green"];


}

SuperType.prototype.sayName=function(){

alert(this.name);

}

function SubType(name,age){

//继承属性

SuperType.call(this,name);

this.age=age;

}

//继承方法

SubType.prototype=new SuperType();

SubType.prototype,constructor=SubType;

SubType.prototype.sayAge=function(){

alert(this.age);

};

var instance1=new SubType("Nicholas"23);

instance1.colors.push("black");

alert(instance1.colors);//"red,blue,green,black"

instance1.sayName();//Nicholas

instance1.sayAge();//23


var instance2=new SubType("Greg",22);

alert(instance1.clolors);//"red,blue,green"

instance2.sayName();//Greg

instance2.sayAge();//22

方式四:原型式继承

借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型

可以通过Object.create()方法来实现原型式继承

方式五:寄生式继承

基本思想:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。

方式六:寄生组合式继承

0 0
原创粉丝点击