彻底理解Javascript原型继承

之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入。

本文试图进一步思考,争取彻底理解Javascript继承原理

实例成员与原型成员

举一个《高性能Javascript》书中例子

var book={
title :"High Performance JavaScript",
publisher:"Yahoo!Press"
};
alert(book.toString());//"[object Object]"

Javascript对象有两种类型的成员:实例成员和原型成员。实例成员存在于实例自身,原型成员则从对象的原型继承

上述示例中,book对象有两个实例成员:title和publisher。book对象并没有定义toString()方法,但是却可以调用这一方法,这是因为toString()方法是book对象继承的一个原型成员

book示例成员与原型成员关系如下图。当book.toString()被调用时,首先从对象实例搜索toString方法,如果没有找到,就转向搜索原型对象。通过这种方式,book可以访问他的原型所有的属性和方法。

原型模式创建对象

function Person(){}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
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"

上述代码中,Person构造函数、原型对象和实例对象见关系如下

将Person属性成员不再定义在原型对象上时

function Person(name)
{
this.name=name;
}
Person.prototype.sayName=function(){alert(this.name)};
var p1=new Person("Zhangsan");

上述代码中,Person构造函数、原型对象和实例对象关系如下图所示

从上面两图可以看出,当属性定义在构造函数中时,属性成员存在于实例对象中;属性定义在原型对象中时,实例对象访问这一属性,需要沿原型链查找该属性

原型链继承

让构造函数的原型对象等于另一个类型的实例,利用原型让一个引用类型继承另一个引用类型的属性和方法

function SuperType()
{
this.property=true;
}
SuperType.prototype.getSuperValue=function(){
return this.property;
};
function SubType()
{
this.subProperty=false;
}
//继承SuperType
SubType.prototype=new SuperType();
SubType.prototype.getSubValue=function(){
return this.subProperty;
} var instance=new SubType();
alert(instance.getSuperValue());//true

代码示例中,完整原型链如下

图中值得注意的细节是,父类SuperType的属性property存在于SuperType的实例对象中,getSuperValue方法存在于其原型对象中

将SuperType实例对象赋给子类SubType的原型对象后,SubType原型对象prototype获得了父类的property属性

换一种写法行不行?

上文是通过将父类的实例对象赋给子类的原型对象,实现了继承的效果

直接将父类的原型对象赋给子类的原型对象行不行?

function Super()
{
this.attr='a';
}
Super.prototype.func=function(){alert('Super');}; function Sub()
{
this.x='1';
} Sub.prototype =Super.prototype; Sub.prototype.test=function(){alert('Sub');} var sub=new Sub();
sub.func();//'Super'
sub.test();//'Sub' sub.attr;//undefined
sub.x;//

上述代码中,将Super.prototype直接赋给Sub.prototpye,发现对Sub类型实例对象sub,访问attr属性时,无法获取

这就是因为attr属性定义在Super构造函数中,而不是定义在Super的原型对象上,此时Super.prototype中并没有attr属性

假设将Super所有属性都定义在原型对象上,如下所示,这时sub实例对象是可以访问到父类的attr属性的

但这时,Super类所有实例对象,都共享了attr属性,一个实例对attr属性的更改,会引起其他实例对象attr属性值的变更,这是应该避免的

function Super()
{
}
Super.prototype.attr='a';
Super.prototype.func=function(){alert('Super');}; function Sub()
{
this.x='1';
} Sub.prototype =Super.prototype; Sub.prototype.test=function(){alert('Sub');} var sub=new Sub(); sub.attr;//a
sub.x;//

再换一种写法看看

function Super()
{
this.attr='a';
}
Super.prototype.func=function(){alert('Super');}; function Sub()
{
this.x='1';
} Sub.prototype =Super(); Sub.prototype.test=function(){alert('Sub');} var sub=new Sub();
sub.func();
sub.test(); sub.attr;
sub.x;

实际上,上面代码会直接报错,提示test属性没有被定义

原因是Sub.prototype=Super();这句代码,实际上是将Sub.prototype指向了undefined,因为Super()语句,是在以函数行驶调用Super()方法,这一调用,是没有返回值的

经过这一调用,Sub.prototype此时已经为undefined,再为他定义test属性,自然就报错了

彻底理解Javascript原型继承的更多相关文章

  1. 深入理解javascript原型和闭包(6)——继承

    为何用“继承”为标题,而不用“原型链”? 原型链如果解释清楚了很容易理解,不会与常用的java/C#产生混淆.而“继承”确实常用面向对象语言中最基本的概念,但是java中的继承与javascript中 ...

  2. 深入理解javascript原型和闭包 (转)

    该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...

  3. 深入理解javascript原型和闭包系列

    从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...

  4. 深入理解javascript原型和闭包(5)——instanceof

    又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...

  5. 深入理解javascript原型和闭包(7)——原型的灵活性

    在Java和C#中,你可以简单的理解class是一个模子,对象就是被这个模子压出来的一批一批月饼(中秋节刚过完).压个啥样,就得是个啥样,不能随便动,动一动就坏了. 而在javascript中,就没有 ...

  6. 深入理解javascript原型和闭包(完结)

    原文链接:http://www.cnblogs.com/wangfupeng1988/p/3977924.html 说明: 该教程绕开了javascript的一些基本的语法知识,直接讲解javascr ...

  7. 深入理解javascript原型和闭包

    目录: 深入理解javascript原型和闭包(1)——一切都是对象 深入理解javascript原型和闭包(2)——函数和对象的关系 深入理解javascript原型和闭包(3)——prototyp ...

  8. 《深入理解javascript原型和闭包系列》 知识点整理(转)

    深入理解javascript原型和闭包系列 对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究. 一.一切都是对象 1. typeof操作符输出6种类型:string boolea ...

  9. 《深入理解javascript原型和闭包系列》 知识点整理

    深入理解javascript原型和闭包系列 对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究. 一.一切都是对象 1. typeof操作符输出6种类型:string boolea ...

随机推荐

  1. GetCursorPos/WindowFromPoint/SendMessage

    GetCursorPos/WindowFromPoint/SendMessage (用API函数向Edit框发送字符) GetCursorPos(mPoint); DTWND:=WindowFromP ...

  2. UVA11069 - A Graph Problem(DP)

    UVA11069 - A Graph Problem(DP) 题目链接 题目大意:给你n个点.要你找出有多少子串符合要求.首先没有连续的数字,其次不能再往里面加入不论什么的数字而不违反第一条要求. 解 ...

  3. alv 列标题

    gs_fieldcat-reptext_ddic才是显示列标题的

  4. Java常用代码段 - 未完待续

    记录一些自己写项目常用的代码段. 格式化常用日期格式 Date date = new Date(System.currentTimeMillis()); DateFormat d3 = DateFor ...

  5. Open Source RTOS

    http://www.osrtos.com/     Name License Platforms Description Last updated FreeRTOS Modified GPL MSP ...

  6. linux log系统图

    log系统图 先贴图,怎么样,效果还不错吧,根据个人理解画的,如果不行将就用着吧.   解说 syslog是一种机制,在wiki中说这种机制可以使用udp,tcp,unix socket等把日志记录在 ...

  7. HDU 1242——Rescue(优先队列)

    题意: 一个天使a被关在迷宫里,她的很多小伙伴r打算去救她.求小伙伴就到她须要的最小时间.在迷宫里有守卫.打败守卫须要一个单位时间.假设碰到守卫必须要杀死他 思路: 天使仅仅有一个,她的小伙伴有非常多 ...

  8. java基础---->摘要算法的介绍 (转)

    数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名.数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密.数据摘要算法也被称为哈希(Hash)算法. ...

  9. 优酷m3u8视频源地址获取失败

    昨天和今天上午,优酷站点视频全然没有办法播放,可是我是获取的优酷视频的视频原地址,所以app还是能够正常播放而且有下载功能.今天下午開始,优酷视频网页能够訪问了,可是视频原地址却不在了.我全部的app ...

  10. Graphviz 绘制流程图

    凝视说明非常具体.不再详述. digraph G{ //dot 是一种画图语言,它能够方便你採用图形的方式高速.直观地表达一些想法, //比方描写叙述某个问题的解决方式,构思一个程序的流程,澄清一堆貌 ...