深入了解javascript中的prototype与继承


Posted in Javascript onApril 14, 2013

通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性列表。javascript创建对象时采用了写时复制的理念。
只有构造器才具有prototype属性,原型链继承就是创建一个新的指针,指向构造器的prototype属性。
prototype属性之所以特别,是因为javascript时读取属性时的遍历机制决定的。本质上它就是一个普通的指针。

构造器包括:
1.Object
2.Function
3.Array
4.Date
5.String

下面我们来举一些例子吧

<script> 
//每个function都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数
//注意Person.constructor 不等于 Person.prototype.constructor. Function实例自带constructor属性 
   function Person(name) {  
        this.name = name;  
    };  
    Person.prototype.getName = function() {  
        return this.name;  
    };  
    var p = new Person("ZhangSan");      console.log(Person.prototype.constructor === Person); // true  
    console.log(p.constructor === Person);  // true ,这是因为p本身不包含constructor属性,所以这里其实调用的是Person.prototype.constructor     
</script>

我们的目的是要表示
1.表明Person继承自Animal
2. 表明p2是Person的实例

我们修改一下prototype属性的指向,让Person能获取Animal中的prototype属性中的方法。也就是Person继承自Animal(人是野兽)

<script> 
   function Person(name) {  
        this.name = name;  
    };  
    Person.prototype.getName = function() {  
        return this.name;  
    };  
    var p1 = new Person("ZhangSan");      console.log(p.constructor === Person);  // true  
    console.log(Person.prototype.constructor === Person); // true  

     function Animal(){ } 
     Person.prototype = new Animal();//之所以不采用Person.prototype  = Animal.prototype,是因为new 还有其他功能,最后总结。 
     var p2 = new Person("ZhangSan"); 
//(p2 -> Person.prototype -> Animal.prototype, 所以p2.constructor其实就是Animal.prototype.constructor)
     console.log(p2.constructor === Person);  // 输出为false ,但我们的本意是要这里为true的,表明p2是Person的实例。此时目的1达到了,目的2没达到。 
</script>

但如果我们这么修正
 
Person.prototype = new Animal();
Person.prototype.constructor = Person;

这时p2.consturctor是对了,指向的是Person,表示p2是Person类的实例,但是新问题出现了。此时目的2达到了,目的1没达到。
目的1和目的2此时互相矛盾,是因为此时prototype表达了矛盾的两个意思,
1表示父类是谁
2作为自己实例的原型来复制

因此我们不能直接使用prototype属性来表示父类是谁,而是用getPrototypeOf()方法来知道父类是谁。

Person.prototype = new Animal();Person.prototype.constructor = Person;
var p2 = new Person("ZhangSan"); 
p2.constructor     //显示 function Person() {}
Object.getPrototypeOf(Person.prototype).constructor     //显示 function Animal() {}

就把这两个概念给分开了

最后总结一下:
当代码var p = new Person()执行时,new 做了如下几件事情:

创建一个空白对象

创建一个指向Person.prototype的指针

将这个对象通过this关键字传递到构造函数中并执行构造函数。

如果采用Person.prototype  = Animal.prototype来表示Person继承自Animal, instanceof方法也同样会显示p也是Animal的实例,返回为true.之所以不采用此方法,是因为下面两个原因:

1.new 创建了一个新对象,这样就避免了设置Person.prototype.constructor = Person 的时候也会导致Animal.prototype.constructor的值变为Person,而是动态给这个新创建的对象一个constructor实例属性,这样实例上的属性constructor就覆盖了Animal.prototype.constructor,这样Person.prototype.constructor和Animal.prototype.contructor就分开了。

2.Animal自身的this对象的属性没办法传递给Person

通过使用 hasOwnProperty()方法,什么时候访问的是实例属性,什么时候访问的是原型属性就 一清二楚了。
 

Javascript 相关文章推荐
Knockout text绑定DOM的使用方法
Nov 15 Javascript
javascript从右边截取指定字符串的三种实现方法
Nov 29 Javascript
JS去除字符串两端空格的简单实例
Dec 27 Javascript
AngularJS extend用法详解及实例代码
Nov 15 Javascript
JavaScript之面向对象_动力节点Java学院整理
Jun 29 Javascript
angularjs实现时间轴效果的示例代码
Nov 29 Javascript
详解node.js 下载图片的 2 种方式
Mar 02 Javascript
vue自动路由-单页面项目(非build时构建)
Apr 30 Javascript
vue element-ui table组件动态生成表头和数据并修改单元格格式 父子组件通信
Aug 15 Javascript
JavaScript和TypeScript中的void的具体使用
Sep 12 Javascript
浅析JavaScript预编译和暗示全局变量
Sep 03 Javascript
微信小程序实现多行文字滚动
Nov 18 Javascript
谈谈JavaScript中的函数与闭包
Apr 14 #Javascript
在新窗口打开超链接的方法小结
Apr 14 #Javascript
JS中setTimeout()的用法详解
Apr 14 #Javascript
js验证是否为数字的总结
Apr 14 #Javascript
JS 实现Json查询的方法实例
Apr 12 #Javascript
js弹出层(jQuery插件形式附带reLoad功能)
Apr 12 #Javascript
location对象的属性和方法应用(解析URL)
Apr 12 #Javascript
You might like
Thinkphp搭建包括JS多语言的多语言项目实现方法
2014/11/24 PHP
PHP+Ajax实现的博客文章添加类别功能示例
2018/03/29 PHP
php正确输出json数据的实例讲解
2018/08/21 PHP
laravel5.6 框架邮件队列database驱动简单demo示例
2020/01/26 PHP
javascript实现的网页局布刷新效果
2008/12/01 Javascript
用js实现的模拟jquery的animate自定义动画(2.5K)
2010/07/20 Javascript
JavaScript之HTMLCollection接口代码
2011/04/27 Javascript
JavaScript实现页面实时显示当前时间的简单实例
2013/07/20 Javascript
JQUERY 设置SELECT选中项代码
2014/02/07 Javascript
javascript中tostring()和valueof()的用法及两者的区别
2015/11/16 Javascript
一个超简单的jQuery回调函数例子(分享)
2016/08/08 Javascript
实现easyui的datagrid导出为excel的示例代码
2016/11/10 Javascript
ztree实现左边动态生成树右边为内容详情功能
2017/11/03 Javascript
javascript实现QQ空间相册展示源码
2017/12/12 Javascript
微信小程序之几种常见的弹框提示信息实现详解
2019/07/11 Javascript
js实现带箭头的进度流程
2020/03/26 Javascript
原生js实现俄罗斯方块
2020/10/20 Javascript
小程序组件传值和引入sass的方法(使用vant Weapp组件库)
2020/11/24 Javascript
Python logging模块学习笔记
2014/05/24 Python
python 字典(dict)遍历的四种方法性能测试报告
2014/06/25 Python
Windows下使Python2.x版本的解释器与3.x共存的方法
2015/10/25 Python
Python3控制路由器——使用requests重启极路由.py
2016/05/11 Python
全面了解Python的getattr(),setattr(),delattr(),hasattr()
2016/06/14 Python
python数字图像处理之骨架提取与分水岭算法
2018/04/27 Python
python读取文本绘制动态速度曲线
2018/06/21 Python
python3 读取Excel表格中的数据
2018/10/16 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
2019/04/15 Python
python3字符串操作总结
2019/07/24 Python
Flask框架钩子函数功能与用法分析
2019/08/02 Python
使用python实现多维数据降维操作
2020/02/24 Python
前端H5 Video常见使用场景简介
2020/08/21 HTML / CSS
香港个人化生活购物网站:Ballyhoo Limited
2016/09/10 全球购物
暑假实习求职信范文
2013/09/22 职场文书
Windows下redis下载、redis安装及使用教程
2021/06/02 Redis
简单且有用的Python数据分析和机器学习代码
2021/07/02 Python
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
2022/04/14 Python