js是一门基于原型的面向对象语言,与传统的面向对象如Java,C#相比,它在对象创建及继承上有自己独特的实现方式,本文主要描述js中对象创建及继承的一些实践。

1.对象创建

方式一:工厂模式创建对象

<script>

    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 a=createPerson('my',27,'student');
a.sayName();
</script>

  这种方式就是将对象属性作为参数传入函数,然后在函数中创建一个新对象再返回给外部使用,属于典型的输入处理输出模式,优点在于简单易于理解也很好的实现了对象的创建和隔离,缺点在于不符合典型OOP语言创建对象实例的做法,而且这样创建出来的对象都属于object类型而不能进一步确定其属于哪个具体的对象类型。

方式二:构造函数创建对象

function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
} }
var p1=new Person('my',27,'stu');
// 这是使用构造函数来创建对象
p1.sayName();

  这种方式使用function来模拟一个类,通过调用这个类的构造函数通过new的方式实例化一个对象,这符合经典OOP创造实例对象的做法,同时也可以确定这个实例属于哪个具体的类型,这里是Person类的实例

,但是这种方式造成的缺点在于每个实例的方法都要在创建该对象时被创建一次,function本质上是一个object,这样做对内存浪费较大,实际上,对于多个不同实例他们的方法是共同引用一个function的关系。

方式三:基于原型创建对象

<script>
function Person(){}
Person.prototype.name='my';
Person.prototype.age=27;
Person.prototype.job='stu';
Person.prototype.sayName=function() {
alert(this.name);
} var p1=new Person(); p1.sayName();
</script>

  这种方式利用每个函数都具有一个原型并且它的多个实例都共享该原型的特性,将该类的属性和方法都挂载到了其原型上,这样做的好处是让多个实例共享了一个方法定义,但是其确定也很明显,即不能通过传参去调用构造函数,构造函数内部的属性都是硬编码的,同时任一实例对其自身的引用类型的属性修改都会影响到其他实例

方式四:构造函数结合原型方式

//属性放在构造函数
//实例间不会相互影响
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
//方法放在原型中
//节省内存
Person.prototype.sayName=function() {
alert(this.name);
} //使用组合方式创建对象
var p1=new Person('my',27,'stu'); p1.sayName();

  这种方式综合了构造函数和原型的优点,将属性等定义5放在构造函数中,实现了不同实例间的隔离,使之不会互相影响,同时又将方法定义挂载到了原型上,使多个实例共享一个方法定义(方法体),节省了内存空间,但是这种方式实际上将两种方式人为分开了,调用构造函数之后还要再去操作其原型,不符合经典OOP语言创建对象的方式。

方法五:动态原型方式

    function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
if(typeof this.sayName!='function'){
this.sayName=function(){
alert(this.name);
}
}
} var p1=new Person('my',27,'stu');
p1.sayName();

  该方式将方法四操作原型的代码直接放入到了构造函数中,同时在new该类型的实例的时候进行判断,如果存在function实例,就不创建,否则创建function,实现了多个实例共享一个方法体的单例模式,该模式也是目前广为使用的,比较好的一种对象实例创建方式。

在创建对象较好实现的基础上,我们来讨论js中的继承。

方式一:基于原型链的继承

function SuperType(){
this.color=['a','b','c']; }
function SubType(){ }
SubType.prototype=new SuperType();
var a1= new SubType();
alert(a1.color);//a,b,c
a1.color.push('d');
var a2=new SubType();
alert(a2.color);//a,b,c,d

  该方法是将子类的原型指向父类的一个实例,子类就具有了父类的方法和属性,但是存在两个缺点,其一是对于父类引用类型的属性来讲,对于其子类任何实例对该属性的操作,其他实例都会受影响,其二是子类继承无法传参到父类,继承的属性无法控制,只能通过修改完成;

方法二:对象冒充继承

function Person(name){
this.name=name;
this.sayName=function(){
alert(this.name);
}
}
function Worker(name,age){
Person.call(this,name);
this.age=age;
}
var w1=new Worker('my',27);
//alert(w1.name);
w1.sayName();

  该种继承方式实现了通过传参去初始化子类的实例,达到了多个实例之间属性方法的隔离,即不会相互影响,但是同样对于方法的继承由于是调用call方法执行父类构造函数中的代码,相当于每次都要创造一个function,这样是对内存的浪费。

方法三:组合继承

 function SuperType(name){
this.name=name; }
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);
} var s1=new SubType('my',27);
s1.sayAge();
s1.sayName();

  该种类型的方法是将对属性的继承采用对象冒充的方式,将对方法的继承基于原型链方式,同时对于父类自身其定义也采取上面所讲的属性定义在构造函数中,方法定义在原型中,这样才能够配合这两种不同方式完成组合继承。

javascript中的对象创建与继承的更多相关文章

  1. js中的对象创建与继承

    对象创建 1.工厂模式 优点:解决了创建多个相似对象的问题 缺点:没有解决对象识别问题:每一个对象都有一套自己的函数,浪费资源 function createPerson(name, age, job ...

  2. javascript中的对象之间继承关系

    相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应,这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达式的不同了,最让我们头疼,恐怕就是面向对象 ...

  3. javascript中的对象,原型,原型链和面向对象

    一.javascript中的属性.方法 1.首先,关于javascript中的函数/“方法”,说明两点: 1)如果访问的对象属性是一个函数,有些开发者容易认为该函数属于这个对象,因此把“属性访问”叫做 ...

  4. Javascript中的对象和原型(3)

    在Javascript中的对象和原型(二)中我们提到,用构造函数创建的对象里面,每个对象之间都是独立的,这样就会降低系统资源的利用率,解决这样问题,我们就要用到下面提到的原型对象. 一 原型对象 原型 ...

  5. JavaScript中的对象描述符(属性特性)

    我们先创建一个对象: var person = { name: "Nicholas", _job: "Software Engineer", sayName: ...

  6. Javascript中的对象和原型(三)(转载)

    在Javascript中的对象和原型(二)中我们提到,用构造函数创建的对象里面,每个对象之间都是独立的,这样就会降低系统资源的利用率,解决这样问题,我们就要用到下面提到的原型对象. 一 原型对象 原型 ...

  7. JavaScript中的对象与原型—你不知道的JavaScript上卷读书笔记(四)

    一.对象 对象可以通过两种形式定义:声明(文字)形式和构造形式.即: var myObj = { key: value // ... }; 或: var myObj = new Object(); m ...

  8. javascript中的对象字面量为啥这么酷

    原文链接 : Why object literals in JavaScript are cool 原文作者 : Dmitri Pavlutin 译者 : neal1991 个人主页:http://n ...

  9. JavaScript中判断对象类型方法大全1

    我们知道,JavaScript中检测对象类型的运算符有:typeof.instanceof,还有对象的constructor属性: 1) typeof 运算符 typeof 是一元运算符,返回结果是一 ...

随机推荐

  1. Markdown 代码块中再内嵌一个行内代码

    在 jQuery 1.9 之前(不含1.9):如果传入一个空字符串. null 或 jQuery.parseJSON( jsonString ) ,该函数将返回,而不是抛出一个错误,即使它不是有效的  ...

  2. Android项目分包---总结-------直接使用

    注: 本文是从该文摘抄而来的.简单的说,就是阅读了该文,然后,再自己复述,复制形成该文.   1.罗列Android项目的分包规则   微盘使用分包规则   如下:     1).第一层com.sin ...

  3. UIAlertView---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址   UIAlertView   //转载请注明出处--本文永久链接:http://ww ...

  4. javascript中数据属性与访问器属性

    1.数据属性 Configurable:true|false,表示能否通过delete将属性删除,默认为true.当把属性的Configurable设置为false后,该属性不能通过delete删除, ...

  5. linux下终端游戏

    sl 一列火车 oneko 一只淘气的小猫

  6. linux===Ubuntu修改设备名称

    step1 sudo vim /etc/hostname 修改你需要的,保存退出 step2 sudo vim /etc/hosts 修改你需要的,保存退出 step3 reboot

  7. monkey测试===修改adb的默认端口

    最近电脑上由于公司系统的原因,adb的端口被占用了,但是占用端口的进程是必须启动的,不能被杀死,在网上找了很多办法,大家都是说杀死占用端口的进程.这个方法并不适用我,所以在此给大家一个新的方法.新建一 ...

  8. python string 对齐文本的几个方法

    用rjust().ljust()和center()方法对齐文本

  9. Linux系统编程——进程间通信(一)

    基本操作命令: ps -ajx/-aux/-ef 查看进程间状态/的相互关系 top 动态显示系统中的进程 nice 按照指定的优先级运行 /renice 改变正在运行的进程的优先级 kill -9杀 ...

  10. tomcat远程调试参数备忘

    tomcat远程调试,启动时添加参数: -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,ser ...