深入了解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创建和操作表格的函数集合
May 07 Javascript
JavaScript日历实现代码
Sep 12 Javascript
jQuery中使用了document和window哪些属性和方法小结
Sep 13 Javascript
JavaScript基本编码模式小结
May 23 Javascript
Javascript排序算法之合并排序(归并排序)的2个例子
Apr 04 Javascript
浅谈javascript中的DOM方法
Jul 16 Javascript
jQuery+CSS实现的网页二级下滑菜单效果
Aug 25 Javascript
js实现兼容IE、Firefox的图片缩放代码
Dec 08 Javascript
解决jquery appaend元素中id绑定事件失效的问题
Sep 12 jQuery
微信小程序实现点击按钮移动view标签的位置功能示例【附demo源码下载】
Dec 06 Javascript
AngularJs分页插件使用详解
Jun 30 Javascript
Node.js+ELK日志规范的实现
May 23 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中动态显示签名和ip原理
2007/03/28 PHP
PHP实现Google plus的好友拖拽分组效果
2016/10/21 PHP
php+ajax无刷新上传图片的实现方法
2016/12/06 PHP
PHP用正则匹配form表单中所有元素的类型和属性值实例代码
2017/02/28 PHP
求解开jscript.encode代码的asp函数
2007/02/28 Javascript
JQuery之拖拽插件实现代码
2011/04/14 Javascript
js将控件隐藏的方法及display属性介绍
2013/07/04 Javascript
node.js下when.js 的异步编程实践
2014/12/03 Javascript
node.js中的fs.readlink方法使用说明
2014/12/17 Javascript
Javascript基础教程之数据类型 (布尔型 Boolean)
2015/01/18 Javascript
js验证身份证号有效性并提示对应信息
2015/10/19 Javascript
javascript图片预加载完整实例
2015/12/10 Javascript
JavaScript开发Chrome浏览器扩展程序UI的教程
2016/05/16 Javascript
jQuery EasyUI Draggable拖动组件
2017/03/01 Javascript
angularjs1.5 组件内用函数向外传值的实例
2018/09/30 Javascript
Node.js + express实现上传大文件的方法分析【图片、文本文件】
2019/03/14 Javascript
全面分析JavaScript 继承
2019/05/30 Javascript
js实现点击烟花特效
2020/10/14 Javascript
[00:32]2018DOTA2亚洲邀请赛EG出场
2018/04/03 DOTA
Python中实现常量(Const)功能
2015/01/28 Python
python使用socket远程连接错误处理方法
2015/04/29 Python
使用python实现rsa算法代码
2016/02/17 Python
Python中的变量和作用域详解
2016/07/13 Python
python中format()函数的简单使用教程
2018/03/14 Python
python 实现返回一个列表中出现次数最多的元素方法
2019/06/11 Python
python 日志 logging模块详细解析
2020/03/31 Python
为什么说python更适合树莓派编程
2020/07/20 Python
html5 Canvas画图教程(3)—canvas出现1像素线条模糊不清的原因
2013/01/09 HTML / CSS
生产副总岗位职责
2013/11/28 职场文书
班风口号
2014/06/18 职场文书
个人学习群众路线心得体会
2014/11/05 职场文书
怎样写辞职信
2015/02/27 职场文书
爸爸的三轮车观后感
2015/06/16 职场文书
党风廉政教育心得体会2016
2016/01/22 职场文书
索尼ICF-36收音机评测
2022/04/30 无线电
Python自动化实战之接口请求的实现
2022/05/30 Python