javascript 原型链维护和继承详解


Posted in Javascript onNovember 26, 2014

一.两个原型

很多人都知道javascript是原型继承,每个构造函数都有一个prototype成员,通过它就可以把javascript的继承演义的美轮美奂了.
其实啊,光靠这一个属性是无法完成javascript的继承.
我们在代码中使用的prototype完成继承在这里就不多说了.大家可以查一下资料.
另外一个看不见的prototype成员.
每一个实例都有有一条指向原型的prototype属性,这个属性是无法被访问到的,当然也就无法被修改了,因为这是维护javascript继承的基础.

//构造器声明

        function Guoyansi(){ }

        function GuoyansiEx(){}

        //原型继承

         GuoyansiEx.prototype=new Guoyansi();

       //创建对象

       var g1=new GuoyansiEx();

       var g2=new GuoyansiEx();

上面的代码中的对象可以用下面的图来说明

javascript 原型链维护和继承详解

二.原型的维护

一个构造器产生的实例,其constructor属性总是指向该构造器.我们暂且认为该话是对的.

function Guoyansi(){ }

var obj1=new Guoyansi();

console.log(obj1.constructor===Guoyansi);//true

其实构造器本身是没有constructor这个属性的,那么这个属性是来自哪呢?
答案是:来自原型.
因此得出下面的结论

obj1.constructor===Guoyansi.prototype.constructor===Guoyansi

既然我们可以通过constructor来寻找构造器.因此我们就可以进一步完善上面的图了.

javascript 原型链维护和继承详解

 function GuoyansiEx(){}

             GuoyansiEx.prototype=new Guoyansi();

             console.log(GuoyansiEx.constructor===GuoyansiEx)//false

根据上图,上面的结果应该是true,但为什么是false呢?

现在做个分析.
GuoyansiEx的原型被Guoyansi的实例重写了,那么GuoyansiEx的原型中的constructor自然也是来自Guoyansi的实例.
而Guoyansi实例中的constructor又是来自Guoyansi.prototype.而Guoyansi.prototype没有被重写,
所以Guoyansi.prototype的constructor指向Guoyansi(构造函数);

根据以上分析得出下面的结论

GuoyansiEx.constructor===Guoyansi.constructor===Guoyansi;

如果在开发过程中对于Constructor的指向要求非常精确的话,可以做如下处理.

/**方法一:**/

 function Guoyansi(){}

             function GuoyansiEx(){}

             GuoyansiEx.prototype=new Guoyansi();

             GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.
/**

            方法二

            **/

            function Guoyansi(){}

            function GuoyansiEx(){

                this.constructor=arguments.callee;

            }

            GuoyansiEx.prototype=new Guoyansi();
/**

            方法三

            **/

            function Guoyansi(){}

            function GuoyansiEx(){

                this.constructor=GuoyansiEx;

            }

            GuoyansiEx.prototype=new Guoyansi();

三.看不见的原型有什么用呢?

看得见的原型链我们可以对他操作来完成我们的继承,那么这个看不见的原型链我们既看不见,又无法操作.要它有何用.
面向对象中继承有一个特性:相似性.子类与父类具有相似性.因此在子类中你是无法用delete删除从父类继承而来的成员.也就是说子类必须具有父类的特性.
为了维护这个特性,javascript在对象的内部产生了一条我们看不见的原型属性,并且不允许用户访问.这样,用户可以处于任何目的来修改constructor,
而不会破坏子类拥有父类的特性.
简而言之:内部原型是javascript的原型继承机制所需要的,而外部原型是用户实现继承所需要的.

四.火狐引擎SpiderMonkey中的__proto__

还是这段代码.

function Guoyansi(){}

            Guoyansi.prototype.age=24;

            function GuoyansiEx(){}

            var obj1=new Guoyansi();

            GuoyansiEx.prototype=obj1;

            GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.

            var obj2=new GuoyansiEx();

我现在想要从obj开始向上访问父类Guoyansi的prototype的属性的age.
思路是这样的.
第一步:obj2====>obj2.constructor.prototype
第二部:obj2.constructor.prototype===>GuoyansiEx.prototype;
第三部:GuoyansiEx.prototype===>obj1;
第四部:obj1.constructor====>Guoyansi
第五部:Guoyansi.prototype.age

写成这这样:console.log(obj2.constructor.prototype.constructor.prototype.age)//24;
最终的结果是24.
最终的结果是24.可以正常执行,但是在好多书上说constructor修改后,级无法在找到父类中的原型了.不知道是怎么回事.

在火狐中提够了一种更加简洁的属性._proto_
SpiderMonkey中默认在任何创建的对象上添加了一个名为_proto_的属性,该属性指向构造器所用的原型.
其实就是我们上面提到的不可见的原型链,只不过是在这个地方变相的公开而已.
可以这样访问到age
console.log(obj2.__proto__.__proto__.age);//24
这样的确是成功的访问到了父类的原型属性,但是这个属性只适用于火狐,在其他浏览器中是会出错的.
在E5中对Object做出了扩展Object.getPrototypeOf(),可以访问到所有父类的原型了.

function Guoyansi(){}

            Guoyansi.prototype.age=24;

            function GuoyansiEx(){}

            var obj1=new Guoyansi();

            GuoyansiEx.prototype=obj1;

            GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.

            var obj2=new GuoyansiEx();

            var proto=Object.getPrototypeOf(obj2);

            while(proto){

                console.log(proto.constructor);

                proto=Object.getPrototypeOf(proto);

            }

            console.log("object的原型"+proto);

结果是:GuoyansiEx
Guoyansi
Object
object的原型null

个人觉得这些应该算是javascript面向对象的精髓之一了.小伙伴们自己参考下,根据需求使用到自己的项目中去吧

Javascript 相关文章推荐
jQuery 树形结构的选择器
Feb 15 Javascript
JavaScript字符串对象slice方法入门实例(用于字符串截取)
Oct 16 Javascript
微信小程序 image组件binderror使用例子与js中的onerror区别
Feb 15 Javascript
详解VUE 定义全局变量的几种实现方式
Jun 01 Javascript
浅谈在vue项目中如何定义全局变量和全局函数
Oct 24 Javascript
JavaScript图片处理与合成总结
Mar 04 Javascript
ES6之模版字符串的具体使用
May 17 Javascript
node中的session的具体使用
Sep 14 Javascript
浅谈让你的代码更简短,更整洁,更易读的ES6小技巧
Oct 25 Javascript
抖音上用记事本编写爱心小程序教程
Apr 17 Javascript
vue中@change兼容问题详解
Oct 25 Javascript
node.js基础知识汇总
Aug 25 Javascript
jquery提示效果实例分析
Nov 25 #Javascript
jQuery操作cookie方法实例教程
Nov 25 #Javascript
JavaScript常用验证函数实例汇总
Nov 25 #Javascript
JavaScript导出Excel实例详解
Nov 25 #Javascript
JS倒计时代码汇总
Nov 25 #Javascript
jquery中push()的用法(数组添加元素)
Nov 25 #Javascript
Jquery焦点图实例代码
Nov 25 #Javascript
You might like
PHP正则表达式替换站点关键字链接后空白的解决方法
2014/09/16 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
PHP多线程模拟实现秒杀抢单
2018/02/07 PHP
PHP笛卡尔积实现原理及代码实例
2020/12/09 PHP
IE6/7 and IE8/9/10(IE7模式)依次隐藏具有absolute或relative的父元素和子元素后再显示父元素
2011/07/31 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
2014/11/13 Javascript
常见JS验证脚本汇总
2015/12/01 Javascript
jquery属性,遍历,HTML操作方法详解
2016/09/17 Javascript
Nginx 配置多站点vhost 的方法
2018/01/07 Javascript
vuejs中监听窗口关闭和窗口刷新事件的方法
2018/09/21 Javascript
React性能优化系列之减少props改变的实现方法
2019/01/17 Javascript
JS实现计算小于非负数n的素数的数量算法示例
2019/02/26 Javascript
基于JavaScript 实现拖放功能
2019/09/12 Javascript
JavaScript键盘事件响应顺序详解
2019/09/30 Javascript
[04:21]狐狸妈带你到现场 DOTA2 TI中国区预选赛线下赛路线指引
2014/05/22 DOTA
[52:00]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs Optic
2018/04/02 DOTA
Python映射拆分操作符用法实例
2015/05/19 Python
在Python中操作字典之clear()方法的使用
2015/05/21 Python
Python字符串转换成浮点数函数分享
2015/07/24 Python
Python 实现 贪吃蛇大作战 代码分享
2016/09/07 Python
python 遍历字符串(含汉字)实例详解
2017/04/04 Python
对pandas的dataframe绘图并保存的实现方法
2017/08/05 Python
python实现发送邮件功能代码
2017/12/14 Python
python奇偶行分开存储实现代码
2018/03/19 Python
使用python制作游戏下载进度条的代码(程序说明见注释)
2019/10/24 Python
Python将列表中的元素转化为数字并排序的示例
2019/12/25 Python
python基于socket函数实现端口扫描
2020/05/28 Python
纯css3实现的鼠标悬停动画按钮
2014/12/23 HTML / CSS
详解基于canvas的视频遮罩插件
2018/01/04 HTML / CSS
国际知名设计师时装商店:Coggles
2016/09/05 全球购物
Eyeko美国:屡获殊荣的睫毛膏、眼线笔和眉妆
2018/07/05 全球购物
详细的大学生创业计划书模板
2014/01/27 职场文书
优秀管理者事迹材料
2014/05/22 职场文书
2014年教学管理工作总结
2014/12/02 职场文书
公务员政审材料
2014/12/23 职场文书
python爬取网页版QQ空间,生成各类图表
2021/06/02 Python