javascript中的对象之间继承关系

  相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应,这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达式的不同了,最让我们头疼,恐怕就是面向对象的部分了,在JavaScript中,是没有给定一个创建对象的关键词的,它不像Java中一个class就可以创建一个对象,在JavaScript中,对象是一个十分松散的的key-value对的组合,通常,我们在创建对象时,可以通过{}来直接生成一个对象,就像我们之前所学的,对象中有属性,有行为,这里我们称为方法,那我们就先来创建一个对象:

          var zhangSan ={name:"张三",age:14}

这就是一个简单的对象,这种方式的优点是简单直接,一眼就可以看出来他的属性和方法但是,这种方法的缺点也很明显,当我们要创建多个对象时,我们就需要一个一个的去创建,一个一个的去赋值,这是十分麻烦而且也不太显示的方法,那么我们可以用工厂法来创建:

 1 function createPeople(name,food){
 2     var people = new object();
 3     people.name=name;
 4     people.eat=function(food){
 5      alert(food);
 6      }
 7     return people;
 8 }
 9 var zhangSan=createPeople("zhangSan","豆腐");
10 zhangSan.eat();//这时会弹出豆腐.

这种方法可以创建多个对象,用个俗一点的话说,就是你想要造多少个人就可以造多少个人,哈哈,那么你以为你这是很好的创建对象的方法了吗?错了,现在我们又有一个问题,就是,我们现在用的这种工厂方法,你并不知道你创建的是一个什么样的类,你创建的people归根底还是由new object()来创建的,和用字面量的方式定义一个类的方法并没有本质上的区别,同样的,我也可以由这个方法创建一条狗,一只猫,一头大象,一条板凳,等等,这样子,类的意义还有什么存在的必要呢,这时,就出现了用构造方法创建类的方法见代码2:

 1 function createPeople(name,age,food){
 2     this.name=name;
 3     this.age=age;
 4     this.food=food;
 5     this.eat=function(){
 6      alert(this.name+"爱吃"+this.food;
 7     }
 8 }
 9 var zhangSan = new createPeople("张三",13,"豆腐");
10 zhangSan.eat();//这是会弹出张三爱吃豆腐这句话

采用这种方法,我们可以避免了上边说的那种不知道创建的是什么类型的对象的那种情况,这里我们要来介绍一下构造方法来创建对象,如果不加new,createPeople()只是一个非常普通的函数,但是在它前边加上new之后,这一切都会变得不同,代码2中第九行的那句话可以分解为两句话来理解:

1 var zhangSan={};//第一步首先创建一个空对象,
2 createPeople.apply(zhangSan arguments);//这一步将函数中的this绑定到zhangSan上,然后就是执行函数中的代码

好了,采用构造函数创建对象,我们可以将这个函数理解成一个类,由这个类可以创造属于它的对像,而不是像上边的工厂方法那样每个对象都没有明确的分类,了解javascript内存管理机智的我们应该都知道,在Javascript中,你每次创建一个对象,堆中就要为这个对象的方法和属性分配一个内存空间,但是对于很多对象来说,它们的属性大都不尽相同,但是很多时候它们的很多方法都是相同的,不同的只是传入的参数的不同而已,这样子是很浪费我们的内存的,这时候,我们就先去了解一下对象的原型链:

  每个函数内都有一个prototype属性,这个prototype属性执行它们的prototype对象,而每一个函数的protocoltype对象中都有一个constructor属性,这个属性指向这个函数本身,

所以问题就来,这是一个很绕口的问题,那么我们就来张图理解一下:

那你说这跟我创建的每一个对象上的方法有神马关系呢?当然有关系了,当我们使用new一个构造方法来创建一个对象的时候,我们创建的那个对象中,也会有一个_proto_属性,这个属性指向构造函数的原型对象,也就是说,在我们对象实例和构造函数之间,它们都指向对象原型,我们每一个对象中都可以继承构造函数原型对象中的属性和方法.那么这就引出了我们要说的内容,就是将我们每个对象都需要的方法放到我们的prototype对象中:

1 function createPeo(userName,hobby){
2     this.userName=userName;
3     this.hobby=hobby;
4     createPeo.prototype.eat=function (){//在对象原型上定义函数,来节省内存;
5         alert(this.userName+"喜欢吃"+this.hobby);
6     }
7 }
8 var shang  = new createPeo("张珊","炒面");
9 var liSi   = new createPeo("李四","撸串");//这样就可以极大的节省了我们的内存,而且每一个对象都能调用到我们的方法 .

好了,现在我们已经成功的创建了一个类,并且由这个类创建了我么所需要的对象,那么我们都知道,有了类,有了对象,我们总是会下意识的去背了起来,累的三大特征:封装,继承,多态,那么在JavaScript中,类的封装是怎么来实现的呢?这个在明天讲述闭包的时候我们再进行讨论,今天我们先来讨论一下类中都有的继承,在我们JavaScript中,类的继承并不像Java中的那样用一个class...extend就行了,在JavaScript中,我们并没有一个class继承的概念,我们用的是很随意的一个原型链的执行继承,就是通过prototype属性来指向想要继承的对象的原型对象,那么我们就开始想,那么我直接用prototype属性指向不就行了吗?

1 function Dog(name,age){
2     this.name=name;
3     this.age=age;
4 }
5 function LittleDog(){}
6 LittleDog.prototype=Dog.prototype;//你以为这样就完成了原型继承,只不过,这样子直接指向原型链的话,你在修改子类的时候,相应的就会修改父类.并且,既然他两个都指向一个原型,那你直接用Dog来创建不就完了了吗,这就失去了继承的意义.

所以,直接将原型链指向父类是不对的,说到这里,我们就可以用一个空函数来作为中转完成原型链的继承:

function Dog(name,age){
    this.name=name;
    this.age=age;
    Dog.prototype.eat=function(){alert("我今年"+this.age+"岁"); }
}
function LittleDog(name,age){
    this.name=name;
    this.age=age;
}

function F(){}
F.prototype=Dog.prototype;
LittleDog.prototype=new F();
LittleDog.prototype.constructor=LittleDog;
var xiaoGou=new LittleDog("旺财",13);
xiaoGou.eat();//这时用小狗调用父类中的方法,返回一个弹框,说明继承成功.

通过这种中间函数来完成类的继承.它并没有改变原有Dog中的原型链条,同时也完成了继承,如果想要在LitteDog中添加原型方法,就可以在new F()中创建方法和属性,当然,我们也可以将这种继承方法封装成一个函数,这样,我们程序的执行效率和美观程度就大大的提升了:

1 function inherits(child,parent){
2      var f = function(){}
3      f.prototype = parent.prototype;
4      child.prototype = new f();
5      child.prototype.constructor=child;
6 }//这是一个封装函数,再进行类的继承时,可以用这个函数来套用.

在类的继承中,除了我们上边说的这种原型继承,还有类继承,以及类继承与原型继承的混用,那么我将在下一章给大家讲解.本博文是博主自创,如果转载请说明出处,谢谢!在下学艺不精,文中如果有什么错误还请高手指正,多谢!

时间: 2024-10-26 06:48:30

javascript中的对象之间继承关系的相关文章

JavaScript中各种对象之间的关系

上图: 此外,补充一下图中用到的概念: 1.内置(Build-in)对象与原生(Naitve)对象的区别在于:前者总是在引擎初始化阶段就被创建好的对象,是后者的一个子集:而后者包括了一些在运行过程中动态创建的对象. 2.引擎扩展对象是一个并不太大的集合,一般来说比较确定,它们也属于引擎的原生对象(但不属于ECMA规范的原生对象). 3.宿主对象不是引擎的原生对象,而是由宿主框架通过某种机制注册到JavaScript引擎中的对象. 4.一些宿主会把自己提供的对象/构造器也称为"原生对象"

java--------【对象之间的关系】

Java中的对象之间的关系有多种,在此之前我着实对这些只是有一点模糊的概念,知道有一次在面试中被面试官问道,才有了这些概念.那就今天借这个机会同大家分享下这个知识点,同时我也在去学习一遍. 1.依赖关系: 这种关系是几种关系中最弱的一种,是对象之间的一种临时关系.例如在一个方法中的返回值供其他对象的调用,这样就与其他的对象建立了一种临时的关系,等调用该方法结束后,他们之间产生的关系也就结束了. 2.关联关系: 所谓的关联关系,对象彼此之间的一种联系.例如淘宝中,用户类与订单类之间的关系,他们彼此

面向对象中多个对象之间的关系

http://www.cnblogs.com/wing011203/archive/2012/06/23/2559223.html 当谈到面向对象的设计时,我们经常说面向对象是符合人们对现实世界的思维模式,即人们采用针对非程序设计领域存在的复杂问题的解决方式,来解决软件设计过程中各种错综复杂的关系.利用面向对象设计,特别是采用各种设计模式来解决问题时,会设计多个类,然后创建多个对象,这些对象,有些主要是数据模型,有些则是行为描述占主体.一个设计良好的类,应该是兼顾信息和行为,并且是高内聚.而不同

javascript中创建对象和实现继承

# oo ##创建对象 1. 原型.构造函数.实例之间的关系 * 原型的construct->构造函数:调用isPrototypeOf(obj)方法可以判定和实例的关系:  * 构造函数的prototype->原型:  * 实例的__proto__ ->原型(仅在chrome,safari,Firefox中存在,而共有的是[[prototype]]):用getPrototypeOf()方法可以返回[[prototype]]的值:  * 构造函数后构造函数的‘子类’new产生一个实例,可以

JavaScript中String对象的match()、replace() 配合正则表达式使用

正则表达式由来已久,查找替换功能非常强大,但模板难记复杂. JavaScript中String对象的match().replace()这2个方法都要使用正则表达式的模板.当模板内容与字符串不相匹配时,match()返回null,replace()返回原字符串. 正则表达式的模板对象 //标准写法 regexp = new RegExp(pattern[, flag]); pattern: 模板的用法是关键,也是本章的主要内容. flag: "i"(ignore)."g&quo

Javascript中的对象和原型(3)

在Javascript中的对象和原型(二)中我们提到,用构造函数创建的对象里面,每个对象之间都是独立的,这样就会降低系统资源的利用率,解决这样问题,我们就要用到下面提到的原型对象. 一 原型对象 原型对象实际上就是构造函数的一个实例对象,和普通的实例对象没有本质上的区别.可以包含特定类型的所有实例的共享属性或者方法.这样,如果我们需要修改所有实例中的属性或者方法,就只需要修改一处,就能够影响到所有实例了.因为原型中的属性和方法是共享的.我们可以看下两个图示:       构造函数方式 原型模式方

JavaScript中的原型和继承

请在此暂时忘记之前学到的面向对象的一切知识.这里只需要考虑赛车的情况.是的,就是赛车. 最近我正在观看 24 Hours of Le Mans ,这是法国流行的一项赛事.最快的车被称为 Le Mans 原型车.这些车虽然是由"奥迪"或"标致"这些厂商制造的,可它们并不是你在街上或速公路上所见到的那类汽车.它们是专为参加高速耐力赛事而制造出来的. 厂家投入巨额资金,用于研发.设计.制造这些原型车,而工程师们总是努力尝试将这项工程做到极致.他们在合金.生物燃料.制动技术

【转】JavaScript中的原型和继承

请在此暂时忘记之前学到的面向对象的一切知识.这里只需要考虑赛车的情况.是的,就是赛车. 最近我正在观看 24 Hours of Le Mans ,这是法国流行的一项赛事.最快的车被称为 Le Mans 原型车.这些车虽然是由“奥迪”或“标致”这些厂商制造的,可它们并不是你在街上或速公路上所见到的那类汽车.它们是专为参加高速耐力赛事而制造出来的. 厂家投入巨额资金,用于研发.设计.制造这些原型车,而工程师们总是努力尝试将这项工程做到极致.他们在合金.生物燃料.制动技术.轮胎的化合物成分和安全特性上

Javascript中的prototype与继承

通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性列表.javascript创建对象时采用了写时复制的理念. 只有构造器才具有prototype属性,原型链继承就是创建一个新的指针,指向构造器的prototype属性. prototype属性之所以特别,是因为javascript时读取属性时的遍历机制决定的.本质上它就是一个普通的指针. 构造器包括: 1.Object 2.Function 3.Array 4.Date 5.String 下面我们来举一些例