彻底理解Javascript原型继承
彻底理解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原型继承的更多相关文章
- 深入理解javascript原型和闭包(6)——继承
为何用“继承”为标题,而不用“原型链”? 原型链如果解释清楚了很容易理解,不会与常用的java/C#产生混淆.而“继承”确实常用面向对象语言中最基本的概念,但是java中的继承与javascript中 ...
- 深入理解javascript原型和闭包 (转)
该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...
- 深入理解javascript原型和闭包系列
从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...
- 深入理解javascript原型和闭包(5)——instanceof
又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...
- 深入理解javascript原型和闭包(7)——原型的灵活性
在Java和C#中,你可以简单的理解class是一个模子,对象就是被这个模子压出来的一批一批月饼(中秋节刚过完).压个啥样,就得是个啥样,不能随便动,动一动就坏了. 而在javascript中,就没有 ...
- 深入理解javascript原型和闭包(完结)
原文链接:http://www.cnblogs.com/wangfupeng1988/p/3977924.html 说明: 该教程绕开了javascript的一些基本的语法知识,直接讲解javascr ...
- 深入理解javascript原型和闭包
目录: 深入理解javascript原型和闭包(1)——一切都是对象 深入理解javascript原型和闭包(2)——函数和对象的关系 深入理解javascript原型和闭包(3)——prototyp ...
- 《深入理解javascript原型和闭包系列》 知识点整理(转)
深入理解javascript原型和闭包系列 对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究. 一.一切都是对象 1. typeof操作符输出6种类型:string boolea ...
- 《深入理解javascript原型和闭包系列》 知识点整理
深入理解javascript原型和闭包系列 对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究. 一.一切都是对象 1. typeof操作符输出6种类型:string boolea ...
随机推荐
- 在DLL动态链接库中封装VCL的MDI子窗体
在DLL动态链接库中封装VCL的MDI子窗体不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下 ...
- lastIndexOf方法——获取字符最后的索引
1.2.20 lastIndexOf方法——获取字符最后的索引 2013-08-29 14:55:18 我来说两句 收藏 我要投稿 本文所属图书 > Java程序开发参考手册 ...
- DBA日常管理——数据归档(Archiving-Data)
原文出处:http://www.sqlnotes.cn/post/2013/09/05/DBA-Daily-Jobs-One%E2%80%94%E2%80%94-Archiving-Data 均为本人 ...
- Problem E: Erratic Ants
这个题没过……!题意:小蚂蚁向四周走,让你在他走过的路中寻找最短路,其中可以反向主要思路:建立想对应的图,寻找最短路径,其中错了好多次,到最后时间没过(1.没有考录反向2.没有考虑走过的路要标记……! ...
- Codeforces Round #256 (Div. 2)总结
这次CF状态之悲剧,比赛就别提了.后来应该好好总结. A题:某个细节没考虑到,导致T了 代码: #include<cstdio> #include<cstring> #incl ...
- Substrings 第37届ACM/ICPC 杭州赛区现场赛C题(hdu 4455)
http://acm.hdu.edu.cn/showproblem.php?pid=4455 https://icpcarchive.ecs.baylor.edu/index.php?option=c ...
- VC 实现视图区背景颜色渐变填充
void CSTest1View::OnDraw(CDC* pDC) { CSTest1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: ...
- 4种Delphi IDE的调试时查看内存的方法,太酷了!
1.ctrl+alt+m,可以查看每个函数过程的内存位置 2.Ctrl+Alt+C 查看代码对应的汇编 3.原来用delphi看变量信息一直是简单的用watch看,但是有时候变量值直接用特定类型看总是 ...
- HDU 4981 Goffi and Median(水)
HDU 4981 Goffi and Median 思路:排序就能够得到中间数.然后总和和中间数*n比較一下就可以 代码: #include <cstdio> #include <c ...
- 使用ffmpeg 对视频截图,和视频转换格式
//执行CMD命令方法 public static void CmdProcess(string command)//调用CMD { //实例化一个进程类 ...