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 相关文章推荐
js 页面输出值
Nov 30 Javascript
原创javascript小游戏实现代码
Aug 19 Javascript
写js时遇到的一些小问题
Dec 06 Javascript
IE6,IE7,IE8下使用Javascript记录光标选中范围(已补全)
Aug 28 Javascript
网站内容禁止复制和粘贴、另存为的js代码
Feb 26 Javascript
jquery 点击元素后,滚动条滚动至该元素位置的方法
Aug 05 Javascript
js css3实现图片拖拽效果
Mar 04 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
Jan 05 Javascript
Vue项目使用CDN优化首屏加载问题
Apr 01 Javascript
layer 刷新某个页面的实现方法
Sep 05 Javascript
Node.js 中如何收集和解析命令行参数
Jan 08 Javascript
利用promise及参数解构封装ajax请求的方法
Mar 24 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 has encountered an Access Violation
2007/01/15 PHP
php实现两个数组相加的方法
2015/02/17 PHP
PHP使用ActiveMQ实现消息队列的方法详解
2019/05/31 PHP
top.location.href 没有权限 解决方法
2008/08/05 Javascript
javascript表单验证使用示例(javascript验证邮箱)
2014/01/07 Javascript
Extjs中RowExpander控件的默认展开问题示例探讨
2014/01/24 Javascript
使用jQuery中的when实现多个AJAX请求对应单个回调的例子分享
2014/04/23 Javascript
通过location.replace禁止浏览器后退防止重复提交
2014/09/04 Javascript
JavaScript基础篇(3)之Object、Function等引用类型
2015/11/30 Javascript
JavaScript动态添加css样式和script标签
2016/07/19 Javascript
通过网页查看JS源码中汉字显示乱码的解决方法
2016/10/26 Javascript
javascript添加前置0(补零)的几种方法
2017/01/05 Javascript
使用jQuery监听扫码枪输入并禁止手动输入的实现方法(推荐)
2017/03/21 jQuery
JS内部事件机制之单线程原理
2018/07/02 Javascript
浅谈一种让小程序支持JSX语法的新思路
2019/06/16 Javascript
Postman动态获取返回值过程详解
2020/06/30 Javascript
原生js实现九宫格拖拽换位
2021/01/26 Javascript
[04:22]DOTA2上海特级锦标赛主赛事第四日TOP10
2016/03/06 DOTA
使用Python简单的实现树莓派的WEB控制
2016/02/18 Python
Python3 操作符重载方法示例
2017/11/23 Python
tensorflow的ckpt及pb模型持久化方式及转化详解
2020/02/12 Python
在jupyter notebook中调用.ipynb文件方式
2020/04/14 Python
matplotlib更改窗口图标的方法示例
2021/02/03 Python
使用CSS媒体查询(Media Queries)和JavaScript判断浏览器设备类型的方法
2014/04/03 HTML / CSS
建筑专业自荐信
2013/10/18 职场文书
公务员政审个人鉴定
2014/02/25 职场文书
巾帼文明岗申报材料
2014/05/01 职场文书
员工年终自我评价
2014/09/14 职场文书
交通安全横幅标语
2014/10/07 职场文书
2014办公室年度工作总结
2014/12/09 职场文书
幼儿园学前班幼儿评语
2014/12/29 职场文书
汽车转让协议书
2015/01/29 职场文书
2015年公共机构节能宣传周活动总结
2015/03/26 职场文书
利用html+css实现菜单栏缓慢下拉效果的示例代码
2021/03/30 HTML / CSS
SQL 尚未定义空闲 CPU 条件 - OnIdle 作业计划将不起任何作用
2021/06/30 SQL Server
我国拿下天问一号火星着陆区附近 22 个地理实体命名:平乐、西柏坡、古田、漠河等
2022/04/29 数码科技