`
dyllove98
  • 浏览: 1378899 次
  • 性别: Icon_minigender_1
  • 来自: 济南
博客专栏
73a48ce3-d397-3b94-9f5d-49eb2ab017ab
Eclipse Rcp/R...
浏览量:38203
4322ac12-0ba9-3ac3-a3cf-b2f587fdfd3f
项目管理checkList...
浏览量:78419
4fb6ad91-52a6-307a-9e4f-816b4a7ce416
哲理故事与管理之道
浏览量:131583
社区版块
存档分类
最新评论

javascript中的继承[一] 原型链介绍

 
阅读更多

废话,可以跳过:好懒,好久没写东西了,总结了好久的正则表达式也没有出炉。最近在干啥,倒叙:git github怎么用,计算机网络,http协议,javascript面向对象,javascriptECMA标准,正则表达式,RESTful原则,php,css inline & block 等等,表示 inline和block还是一塌糊涂,等待研究。需要学的东西好多,亚历山大~~~

 

前言:可能会写三到四篇关于js链式继承以及面向对象的东西,大都是不同书籍的笔记、总结以及自己的理解。

涉及的书:

1.Object-Oriented JavaScript

2.Professional JavaScript for Web Developers[红书,javascript高级程序设计]

3.JavaScript Web Applications

 

正文

(一)javascript中"类"的继承是基于原型链的。什么是原型[prototype]链?

先举个例子

[想这个例子好纠结,纠结于js中“类”和Php、C#、java中类的含义其实是不一样的,我纠结于是否有必要阐述下两者的不同,想想还是算了。也许后文慢慢会说明白。如果你对其他语言中类的含义有所理解,希望在理解原型的时候,更多的是比较有何不同,着重理解原型链的本质,不要急于想用原型怎么达到类的效果。]

[我们可以用原型链做很多有趣事情,不用较真js如何构造一些诸如private public static 等关键字的实现]

类可以理解为种类,是一些特性的集合;对象是类的实现,是具体特性的实现。

动物,马,人,车都可以看做是类,是概念;具体到他家的狗,他妹,他家的车都是实物,是对象。

面向对象的程序设计,这种说法不一定确切,但是可以这么粗糙的理解。

继续举例子

原型链 更像是“我爸是李刚”,我儿子有事,先找我,我如果有事解决不了,就找李刚。

js中的每个对象,都包含有一个指针,指向它的原型。当我们调用一个js对象obj的属性或者方法时,obj先在直接属于自己的属性、方法中找,如果找不到,就在它的原型里找,如果找不到,再在原型的原型里找。

我是一个人,一个对象,我爹也是个人,一个对象。我儿子办成什么事情,外人不一定清楚到底是谁的本事。

objA是一个对象,它的原型objB也是一个对象,objC也是一个对象,每个对象都有他们自己的属性和方法。当objA.fun()执行时,如果objA不含有fun这个方法,解释器会在objA的原型对象objB查找,一直向上找。我自己认为,这种原型链的思想,不一定理解成父子的关系,也不一定要理解成继承关系。就像社会关系,不一定只是父子,也可以是师生、朋友。

这是原型链的一个概貌。和普遍意义上类的继承有很大差距,其他语言中如果按照“链”的方式去理解继承关系,更多是在类(Class)层面上,鸟有飞的方法,马和牛都是哺乳动物,他们都是生物。javascript是没有类(Class)这一说法的。

 

(二)原型如何实现

构造对象一般会见到两种最基本的形式:字面量和构造函数

/*字面量*/
var jim = {};
jim.name = "Jim";
jim.sayHello = function(){alert(this.name);};

var hanmeimei = {
    name:"hanmeimei",
    sayHello:function(){alert(this.name);}
};

/*构造函数*/

function Person(name){
    this.name = name;
    this.sayHello = function(){alert(this.name);};

}
var zhangsan = new Person("zhangsan");
var lisi = new Person("lisi");
lisi.toString();

上面的代码中,原型在哪里??(不知道能扯多远,本来第一篇文章是讲o-o javascript那本书的笔记的,哎,就变成js对象基础介绍了)

javascript中函数也是一种对象,我们定义的Person 是Function的实例。

原型是函数实例的一个属性。

原型本身是一个对象,他是在函数定义的时候创建的。

Person定义的过程中,Person会得到一个prototype的属性,指向一个内部生成的对象(就是一个普通的Object)。执行 如lisi.toString();的时候,这个方法其实是这个原型对象的。

lisi又是如何和Person的原型对象扯上关系的呢?

var lisi = new Person("lisi");

这简单的一句话,华丽丽地做好好多你不知道的事情,比如说一下这些(有很多,具体可以参看ECMA的标准)

1.实例化一个Object对象,Person函数中的this指向这个对象

2.给这个对象加上一个内部私有属性(如__proto__,不通的浏览器宿主实现不一样),指向Person的原型(函数的原型对象是在函数定义的时候产生的,现在是实例化一个对象,这是两个过程)

3.执行函数Person中的代码

4.如果函数Person的返回值不是对象,或者没有返回值,返回步骤1中生成的对象;如果有返回值,返回这个对象。

 

小结:

1.原型(prototype)是函数的一个属性,原型对象在函数定义时产生。

2.通过构造函数产生对象的时候,这个对象会有一个内部属性(__proto__),指向函数的原型对象。

3.一个对象没有实现某方法、属性时,会向它内部指向的原型去查找。

 

(三)我们如何通过上面的小结,用原型链实现继承??

我们尝试地基于Person"类",实现一个Coder"类",继承Person的属性和方法。

function Person(name){
    this.name = name;
    this.sayHello = function(){alert(this.name);};
}
function Coder(language){
   this.language = language;
    this.code = function(){alert("i am a "+this.language+" coder");};
}

Coder.prototype = new Person("无名");

var c1 = new Coder("js");
c1.sayHello();
c1.code();

var c2 = new Coder("js");

c2.sayHello();
c2.name = "jim";
c2.sayHello();
c2.code();
 

 

你能理解吗?运行下看看~~~

 

 

 

 

 

 

 

 

//这是Person构造函数
//函数定义的时候,会产生一个原型对象,Person.prototype指向这个对象
function Person(name){
    this.name = name;
    this.sayHello = function(){alert(this.name);};
}

//这是Coder构造函数
//函数定义的时候,会产生一个原型对象,Coder.prototype指向这个对象
function Coder(language){
   this.language = language;
    this.code = function(){alert("i am a "+this.language+" coder");};
}

//这里是关键,我们修改了原生的原型对象,而是把prototype指向一个Person的实例,后面还会再次详细解释。
Coder.prototype = new Person("无名");
var c1 = new Coder("js");
c1.sayHello();
c1.code();


//执行构造函数,对象c有个内部属性(__proto__)指向Coder的原型对象
 var c2 = new Coder("js"); 

//c2此时没有name属性,会查找原型对象中的name属性 
alert(c2.name); 

//给c2增加name属性,此处再做解释 
c2.name = "jim"; 

//同样,c2没有sayHello方法,执行的是原型对象的方法  
c2.sayHello(); 

//c2自己的方法 
c2.code();

 

我们人工的修改了Coder的prototype属性,指向一个Person的实例。

c2调用sayHello方法的时候,自己没有这个方法,就会通过__proto__指针查找Coder原型对象(即我们Person("未命名")产生的实例)的属性,找到sayHello执行即可。

特别需要注意的是,c2.name = "jim" 并不是修改了 原型对象的name属性,而是给c增加了name属性,并赋值”jim“。因为,Coder的实例只能通过__proto__获取原型对象的属性、方法,并无权修改。原型对象的属性、方法只能通过如 Coder.prototype.name = "XXX" 这种方式去修改。我写上面代码注释,起初写的是错的,只是犹豫不觉,最后和js群里尼奥交流了下,才意识到错了。

 

现在你能看出点端倪来了吗?Coder原型中的方法、属性,是实例共享的,实例通过__proto__指针可以访问原型中的属性方法,但是不能修改。这是基于原型继承的基本原理。

上面不是js继承最好的实现,只是个入门的介绍。不用纠结new Coder() 构造函数不可以传姓名,以及Coder.prototype = new Person("未命名")这种蹩脚的写法。这篇文字还停留在介绍原型基本原理,并顺便说了几句面向对象的基本概念。后面的章节会介绍很多js继承的实践,会按照书中的逻辑,一本一本的介绍(其实是写读书笔记)。

本章描述的原型链的概念,几乎可以在所有介绍js的主流书中找到,很多博客中也有详细说明。最后用一幅图作为结束:

 你看懂了吗?下篇解释~~晚安

1
5
分享到:
评论
1 楼 rockis 2013-06-03  
红底黑字看着难受

相关推荐

    JavaScript你一定要搞懂的原型链

    当访问一个对象的属性或方法时,如果对象本身没有定义该属性或方法,JavaScript 就会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的末尾(null)为止。 原型链图是用于表示 JavaScript 中对象之间原型...

    JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)

    说好的讲解JavaScript继承,可是迟迟到现在讲解。废话不多说,直接进入正题。  既然你想了解继承,证明你对JavaScript面向对象已经有一定的了解,如还有什么不理解的可以参考《面向对象JS基础讲解,工厂模式、构造...

    JavaScript使用原型和原型链实现对象继承的方法详解

    主要介绍了JavaScript使用原型和原型链实现对象继承的方法,简单讲述了javascript原型与原型链的原理,并结合实例形式详细分析了javascript中对象继承的常见实现技巧,需要的朋友可以参考下

    强大的原型和原型链

    JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型。...由于 JavaScript 是唯一一个被广泛使用的基于原型继承的语言,所以理解两种继承模式的差异是需要一定时间的,今天我们就来了解一下原型和原型链

    JavaScript原型继承和原型链原理详解

    这篇文章主要介绍了JavaScript原型继承和原型链原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在讨论原型继承之前,先回顾一下关于创建自定义类型的...

    Javascript原型链的原理详解

    在JavaScript中,用 __proto__ 属性来表示一个对象的原型链。当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止! 比如现在有如下的代码: 扩展Object类,添加Clone和Extend方法 /...

    深入理解javascript原型链和继承

    在上一篇文章中,介绍了原型的概念,了解到在javascript中构造函数、原型对象、实例三个好基友之间的关系:每一个构造函数都有一个“守护神”——原型对象,原型对象心里面也存着一个构造函数的“位置”,两情相悦,...

    一篇文章让你搞懂JavaScript 原型和原型链

    原型和原型链作为深入学习JavaScript最重要的概念之一,如果掌握它了后,弄清楚例如:JavaScript的继承,new关键字的原来、封装及优化等概念将变得不在话下,那么下面我们开始关于原型和原型链的介绍。 什么是原型?...

    JavaScript原型链与继承操作实例总结

    主要介绍了JavaScript原型链与继承操作,结合实例形式总结分析了javascript原形链与继承的相关概念、使用方法及操作注意事项,需要的朋友可以参考下

    JavaScript基于原型链的继承

    原型链是JavaScript中继承的主要方法。 原型链的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。 构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数...

    js中的继承与原型链1

    当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾

    详解JavaScript原型与原型链

    了解JavaScript的继承与原型链之前首先需要了解JavaScript中对象创建的方式。 在JavaScript中创建对象 JavaScript中对象创建的方式有两种:工厂方法(Factory Functions)、构造器方法(Constructor Functions) 。 ...

    【JavaScript源代码】五句话帮你轻松搞定js原型链.docx

     原型链是一种机制,指的是JavaScript每个对象包括原型对象都有一个内置的[[proto]]属性指向创建它的函数对象的原型对象,即prototype属性。 作用:原型链的存在,主要是为了实现对象的继承。 一、 记住以下5句话...

    js 原型对象和原型链理解

    而Object的原型对象用Object.__proto__ = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。原型对象的用途是为每个实例对象存储共享...

    js对象继承之原型链继承实例

    本文实例讲述了js对象继承之原型链继承的用法。分享给大家供大家参考。具体分析如下: 代码如下:[removed] //定义猫的对象 var kitty = {color:’yellow’,bark:function(){alert(‘喵喵’);},climb:...

    JavaScript核心(对象、原型、继承、上下文、闭包、this).pdf

    面向对象概念(对象封装,各种继承,闭包原理,this作用域等)介绍清晰易懂

    js实现的七种继承方式.md

    使用js实现继承的七种方式,详细讲解了js中的原型链继承,构造函数继承,组合继承(经典继承),原型式继承,寄生式继承,寄生组合式继承,以及ES6中的继承,描述原理以及实现和要点概述等。

Global site tag (gtag.js) - Google Analytics