博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
彻底理解Javascript原型继承
阅读量:7070 次
发布时间:2019-06-28

本文共 2973 字,大约阅读时间需要 9 分钟。

彻底理解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;}//继承SuperTypeSubType.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;//undefinedsub.x;//1

上述代码中,将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;//asub.x;//1

 

再换一种写法看看

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属性,自然就报错了

 

转载于:https://www.cnblogs.com/GongQi/p/4550226.html

你可能感兴趣的文章
2019年,AI安防行业的10大未知丨中国人工智能安防峰会
查看>>
Guidelines for Function Compute Development - Use Fun Local for Local Running and Debugging
查看>>
pycharm Startup Error: Application cannot start in headless mode
查看>>
vue-03
查看>>
NG-ZORRO 7.1.0 发布,Ant Design 的 Angular 实现
查看>>
jQuery图片垂直滚动焦点图
查看>>
使用镜像搭建WordPress网站过程
查看>>
【对讲机的那点事】你了解TETRA数字集群通信系统组网的模式吗?
查看>>
【问答集锦】技术与运营的多面手赵亚飞,内存溢出怎么处理?
查看>>
jQuery选择器总结
查看>>
阿里最全面试116题:阿里天猫、蚂蚁金服、阿里巴巴面试题含答案
查看>>
elasticsearch的score相关资料(整理)
查看>>
SQL Tune Report–sqltrpt.sql
查看>>
Cobbler
查看>>
JNI开发极简教程
查看>>
Bugku -代码审计(urldecode二次编码绕过)
查看>>
Auto Layout 使用心得(五)—— 根据文字、图片自动计算 UITableViewCell 高度
查看>>
Linux命令参数详细解析-cp
查看>>
python爬取糗事百科
查看>>
Java 创建文件
查看>>