Javascript中的prototype与继承


Posted in Javascript onFebruary 06, 2017

通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性列表。javascript创建对象时采用了写时复制的理念。

只有构造器才具有prototype属性,原型链继承就是创建一个新的指针,指向构造器的prototype属性。

prototype属性之所以特别,是因为javascript时读取属性时的遍历机制决定的。本质上它就是一个普通的指针。

构造器包括:

1.Object
2.Function
3.Array
4.Date
5.String

下面我们来举一些例子吧

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

我们的目的是要表示

1. 表明Person继承自Animal

2. 表明p2是Person的实例

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

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

但如果我们这么修正

Person.prototype = new Animal();
Person.prototype.constructor = Person;

这时p2.consturctor是对了,指向的是Person,表示p2是Person类的实例,但是新问题出现了。此时目的2达到了,目的1没达到。

目的1和目的2此时互相矛盾,是因为此时prototype表达了矛盾的两个意思,

1. 表示父类是谁

2. 作为自己实例的原型来复制

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

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

就把这两个概念给分开了 ,其实通过使用 hasOwnProperty()方法,什么时候访问的是实例属性,什么时候访问的是原型属性就一清二楚了

new做了哪些事情?

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

创建一个空白对象

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

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

具体点来说,在下面这段代码中,

Person.prototype.getName =function(){}

如果我们通过

var person =newPerson();
其实类似于
var person =newObject();
person.getName =Person.prototype.getName;

因此通过person.getName()调用方法时,this指向的是这个新创建的对象,而不是prototype对象。

这其实在给现有函数加上新功能的情况下会用到,我们可以这么扩展现有的方法:

//function myFunc 的写法基本上等于 var myFunc = new Function();
function myFunc (){
}
myFunc =function(func){
//可以在这里做点其他事情
returnfunction(){


 //可以在这里做点其他事情
return func.apply(this,arguments);
}
}(myFunc)

也可以在Function.prototype方法里直接通过this来访问上面代码的myFunc所指向的对象

function myFunc (){
}
if(!Function.prototype.extend){
Function.prototype.extend =function(){
var func =this;
returnfunction(){
func.apply(this,arguments);
}
}
};
var myFunc = myFunc.extend();

总结一下

如果采用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

但是像下面这样直接调用构造函数又可能失败,或者产生其他影响。

Person.prototype =newAnimal();

为了避免这种情况,所以我们引入了一个中间函数。所以正确的做法应该是

Person.prototype =(funtion(){
 function F(){};
 
F.prototype =Animal.prototype
 
returnnew F();
})()

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript 工具库 Cloudgamer JavaScript Library v0.1 发布
Oct 29 Javascript
js获取当前地址 JS获取当前URL的示例代码
Feb 26 Javascript
Node.js编码规范
Jul 14 Javascript
上传图片js判断图片尺寸和格式兼容IE
Sep 01 Javascript
JavaScript lastIndexOf方法入门实例(计算指定字符在字符串中最后一次出现的位置)
Oct 17 Javascript
JS实现固定在右下角可展开收缩DIV层的方法
Feb 13 Javascript
jquery中map函数遍历数组用法实例
May 18 Javascript
AngularJS基础教程之简单介绍
Sep 27 Javascript
详解vue+css3做交互特效的方法
Nov 20 Javascript
vue-cli 组件的导入与使用教程详解
Apr 11 Javascript
js事件on动态绑定数据,绑定多个事件的方法
Sep 15 Javascript
解决Vue+Electron下Vuex的Dispatch没有效果问题
May 20 Javascript
canvas实现粒子时钟效果
Feb 06 #Javascript
javascript笔记之匿名函数和闭包
Feb 06 #Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
Feb 06 #Javascript
D3.js中强制异步文件读取同步的几种方法
Feb 06 #Javascript
浅谈Javascript事件对象
Feb 05 #Javascript
js中创建对象的几种方式
Feb 05 #Javascript
js实现增加数字显示的环形进度条效果
Feb 05 #Javascript
You might like
PHP学习之正则表达式
2011/04/17 PHP
理解和运用PHP中的多态性[译]
2011/08/02 PHP
php报表之jpgraph柱状图实例代码
2011/08/22 PHP
PHP fgetcsv 定义和用法(附windows与linux下兼容问题)
2012/05/29 PHP
php float不四舍五入截取浮点型字符串方法总结
2013/10/28 PHP
CI框架中zip类应用示例
2014/06/17 PHP
PHP中使用addslashes函数转义的安全性原理分析
2014/11/03 PHP
PHP合并discuz用户脚本的方法
2015/08/04 PHP
php网页版聊天软件实现代码
2016/08/12 PHP
php动态读取数据清除最右边距的方法
2017/04/12 PHP
Windows 下安装 swoole 图文教程(php)
2017/06/05 PHP
JQuery的html(data)方法与<script>脚本块的解决方法
2010/03/09 Javascript
JAVASCRIPT实现的WEB页面跳转以及页面间传值方法
2010/05/13 Javascript
从零开始学习jQuery (八) 插播:jQuery实施方案
2011/02/23 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
Jquery节点遍历next与nextAll方法使用示例
2014/07/22 Javascript
基于Bootstrap+jQuery.validate实现Form表单验证
2014/12/16 Javascript
Jquery实现图片预加载与延时加载的方法
2014/12/22 Javascript
jQuery实现仿微软首页感应鼠标变化滑动窗口效果
2015/10/08 Javascript
简介EasyUI datagrid editor combogrid搜索框的实现
2016/04/01 Javascript
Bootstrap select实现下拉框多选效果
2016/12/23 Javascript
Vue.js单向绑定和双向绑定实例分析
2018/08/14 Javascript
vue-router实现嵌套路由的讲解
2019/01/19 Javascript
layui按条件隐藏表格列的实例
2019/09/19 Javascript
用Python制作在地图上模拟瘟疫扩散的Gif图
2015/03/31 Python
Python素数检测实例分析
2015/06/15 Python
python+selenium识别验证码并登录的示例代码
2017/12/21 Python
对python numpy.array插入一行或一列的方法详解
2019/01/29 Python
python函数的作用域及关键字详解
2019/08/20 Python
conda安装tensorflow和conda常用命令小结
2021/02/20 Python
HTML5 canvas 瀑布流文字效果的示例代码
2018/01/31 HTML / CSS
党的群众路线教育实践活动心得体会900字
2014/03/07 职场文书
大学信息公开实施方案
2014/03/09 职场文书
股权转让协议书
2014/12/07 职场文书
残联2016年全国助残日活动总结
2016/04/01 职场文书
在Spring-Boot中如何使用@Value注解注入集合类
2021/08/02 Java/Android