深入了解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 相关文章推荐
在js文件中如何获取basePath处理js路径问题
Jul 10 Javascript
javascript定义变量时有var和没有var的区别探讨
Jul 21 Javascript
自定义刻度jQuery进度条及插件
Sep 02 Javascript
javascript 判断页面访问方式电脑或者移动端
Sep 19 Javascript
Angular项目从新建、打包到nginx部署全过程记录
Dec 09 Javascript
解决vue-router中的query动态传参问题
Mar 20 Javascript
JS中使用new Option()实现时间联动效果
Dec 10 Javascript
用node开发并发布一个cli工具的方法步骤
Jan 03 Javascript
操作按钮悬浮固定在微信小程序底部的实现代码
Aug 02 Javascript
jquery树形插件zTree高级使用详解
Aug 16 jQuery
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
Aug 20 Javascript
JavaScript实现简单计时器
Jun 22 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
PHP获取当前日期所在星期(月份)的开始日期与结束日期(实现代码)
2013/06/18 PHP
解析mysql中UNIX_TIMESTAMP()函数与php中time()函数的区别
2013/06/24 PHP
php通过array_merge()函数合并关联和非关联数组的方法
2015/03/18 PHP
PHP设计模式之 策略模式Strategy详解【对象行为型】
2020/05/01 PHP
javascript 自动填写表单的实现方法
2010/04/09 Javascript
扩展Jquery插件处理mouseover时内部有子元素时发生样式闪烁
2011/12/08 Javascript
Javascript实现重力弹跳拖拽运动效果示例
2013/06/28 Javascript
artDialog双击会关闭对话框的修改过程分享
2013/08/05 Javascript
js 获取、清空input type=&quot;file&quot;的值示例代码
2014/02/19 Javascript
详解vue.js的事件处理器v-on:click
2017/06/27 Javascript
Angularjs 手写日历的实现代码(不用插件)
2017/10/18 Javascript
elemetUi 组件--el-upload实现上传Excel文件的实例
2017/10/27 Javascript
解读vue生成的文件目录结构及说明
2017/11/27 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
2018/05/18 Javascript
Nuxt配合Node在实际生产中的应用详解
2018/08/07 Javascript
详解Angular6学习笔记之主从组件
2018/09/05 Javascript
原生JS实现的放大镜特效示例【测试可用】
2018/12/08 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
Vue.js实现可编辑的表格
2019/12/11 Javascript
Python实现的数据结构与算法之快速排序详解
2015/04/22 Python
Python获取系统默认字符编码的方法
2015/06/04 Python
django admin添加数据自动记录user到表中的实现方法
2018/01/05 Python
python语音识别实践之百度语音API
2018/08/30 Python
python实现给scatter设置颜色渐变条colorbar的方法
2018/12/13 Python
Django将默认的SQLite更换为MySQL的实现
2019/11/18 Python
如何用python写个模板引擎
2021/01/14 Python
HTML5 Canvas画线技巧——实现绘制一个像素宽的细线
2013/08/02 HTML / CSS
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
英国在线药房和在线医生:LloydsPharmacy
2019/10/21 全球购物
金智子午JAVA面试题
2015/09/04 面试题
广告宣传策划方案
2014/05/21 职场文书
党员自我剖析材料
2014/08/31 职场文书
党的群众路线对照检查材料思想汇报
2014/09/25 职场文书
2015年政协委员工作总结
2015/05/20 职场文书
2016年小学生寒假家长评语
2015/10/10 职场文书
Win10防火墙白名单怎么设置?Win10添加防火墙白名单方法
2022/04/06 数码科技