您的位置:首页 > Web前端 > JavaScript

javascript 面向对象的对象创建与继承

2012-11-19 11:52 585 查看
javascript中对象的定义:无序属性的集合,其属性包含基本值、对象或者函数。

javascript中有两种属性:数据属性和访问器属性。
数据属性包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有4个描述其行为的特性。
1.[[Configurable]]:表示能否通过delete删除属性和重新定义属性。
2.[[Enumerable]]:表示能否通过for-in循环返回属性。
3.[[Writeable]]:表示能否修改属性的值
4.[[Value]]:表示这个属性的值

实例:
javascript: var person={}; Object.defineProperty(person,"name",{writable:false,value:"seacean"}); console.log(person.name); person.name="hello wrold!"; console.log(person.name);
运行结果显示是



这些数据属性的配置如果有设置,在严格模式下进行非法操作会返回错误,非严格模式会忽略。

访问器属性不包含任何数值,包含一对get/set函数。

1.[[Configurable]]:表示能否通过delete删除属性和重新定义属性。
2.[[Enumerable]]:表示能否通过for-in循环返回属性。

3.[[get]]:在读取属性的时候调用的函数
4.[[set]]:在设置属性的时候调用的函数
访问器的属性和数据属性一样,只能使用Object.defineProperty来进行定义。这样的话,数据属性和访问器属性可以同时定义。
定义多个属性的方法是Object.defineProperties.

创建对象的方法

工厂模式

function createPerson(name,age,job){
var o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function(){ return this.name;};
return o;
}


javascript:
function createPerson(name,age,job){ var o=new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ return this.name;}; return o; }
这是一个创建Person类的工厂方法

构造函数方式

function Person(){
this.name="nicole";
}

原型模式

function Person(){};
Person.prototype.name="nicole";

这些方法各有优缺点,工厂无法让创建变得更像面向对象,构造函数无法保存类共享属性,原型的所有属性都是共享的。

结合各自的优缺点,我们使用构造函数创建每个类中非静态的属性和方法,原型创建类中的静态属性和方法。
function Man(obj){
this.name=obj.name;
}

Man.prototype={
constructor:Person,
sayName:function(){alert(this.name);}
}

还有一类安全程度更高的构造函数,成为稳妥构造函数,不使用this,不使用new操作符调用构造函数,与别的对象没有关联

function Person(name,age,job){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.job=job;
return obj;
}

一般情况下我们用不到使用继承这种情况,使用到继承这种情况的时候大多是定义框架,开发组件等等。而且一般的web开发是用不到继承的。但是一用到继承就说明面对的情况很复杂。

面向对象的继承关系显得有些复杂
js的继承是实现上的继承,造成继承的事实。
原型链方式继承
function SuperType(){
this.property=true;
}

SuperType.prototype.getSuperValue=function(){
return this.property;
}

function SubType(){
this.subproperty=false;
}

SubType.prototype=new SuperType();

SubType.prototype.getSubValue=function(){
return this.subproperty;
}

var instance=new SubType();
alert(instance.getSuperValue());

这个说明了继承的含义和形式,继承就是采用上面的样子,不断扩展原型。
也可以将SuperType里面的全部属性和方法copy到SubType中,造成事实上的继承关系。

继承关系中的方法重写
在SubType.prototype=new SuperType();之后可以添加对里面方法的重写为SubType.prototype.getSuperValue=function(){
return this.subproperty;
}

继承的另一种方式
使用call,apply方法
借用构造函数式继承
function SuperType(name){
this.name=name;
this.colors=["red","yellow","orange"];
}

function SubType(){
SuperType.call(this,"max");
this.age=100;
}

组合继承方式,组合前面两种情况

function SuperType(name){
this.name=name;
this.colors=["red","yellow","orange"];
}

SuperType.prototype.sayName=function(){
alert(this.name);
}

function SubType(name,age){
SuperType.call(this,name);
this.age=age;
}

SubType.prototype=new SuperType();
SubType.prototype.sayAge=function(){
alert(this.age);
}

这样子类本身通过构造函数可以扩展,通过prototype也可以扩展

原型式继承
基于已有的对象创建新的对象,同时还不必因此创建新的对象

function getPerson(/*object*/ obj){
function F(){}
F.prototype=obj;
return new F();
}
obj是已将存在的对象,新对象的类型不需要给出明确定义

寄生式继承
function createAnother(original){
var clone=getPerson(original);//进行新的包装
clone.color="red";
clone.sayColor=function(){alert(this.color);};
return clone;
}
在这里面,original是一个已存在的对象,进入函数内要进行添加新的属性和方法,返回一个新的对象。这个不是通过构造函数方式运作的。

寄生组合式继承

function SuperType(name){
this.name=name;
this.colors=["red","yellow","orange"];
}

SuperType.prototype.sayName=function(){
alert(this.name);
}

function SubType(name,age){
SuperType.call(this,name);
this.age=age;
}

function inheritPrototype(subType,superType){
var proto=object(superType.prototype);
proto.constructor=subType;
subType.prototype=proto;
}

inheritPrototype(SubType,SuperType);
//对子类父类之间的关系进行修正

SubType.prototype.sayAge=function(){
alert(this.age);
}

这种继承方式只引用了一次构造函数,不改变其它东西。这种方式是目前最理想的继承方式。

var person={};
Object.defineProperty(person,"name",{writable:false,value:"seacean"});
console.log(person.name);
person.name="hello wrold!";
console.log(person.name);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: