javascript中继承(一)-----原型链继承的个人理解
【寒暄】好久没有更新博客了,说来话长,因为我下定决心要从一个后台程序员转为Front End,其间走过了一段漫长而艰辛的时光,今天跟大家分享下自己对javascript中原型链继承的理解。
总的说来,js中的常用的继承方式可以分为两种,一种是原型链式继承,这也是本文要谈的重点;另外一种是借用构造函数继承,这方面的理解,我将在下次的博客中更新。好了,闲话不多说,进入正题。
一,关于原型
function Person(){}//这里我们声明一个函数Person,js中函数是对象,也是构造函数
console.log(Person.prototype)//打印一下Person对象的原型,会出现什么呢?如下图所示:
大家在图中看到了,Person对象的原型拥有一个constructor,它指向Person的构造函数,即Person本身,另外一个属性是__proto__属性,这个属性我会在后文中说明。
到这里,大家肯定会明白了,一个对象建立后,会产生一个局部的“小链式结构”,即Person对象拥有一个prototype属性,这个属性指向原型对象,在原型对象中又有一个构造器constructor,指向构造函数。用一张图来说明:
那么,原型对象的作用是什么呢?这个原型对象包含由特定类型的实例共享的属性和方法。大家要注意共享这两个字,用一段代码解释下
function Person(){
this.name="bob" //这是一个实例属性
}
Person.prototype.eat=function(){ //给对象的原型对象添加一个eat的方法,接下来,new的实例会共享这个方法
return "food";
}
var p1=new Person(); //这里究竟发生生了什么?
p1.eat()//->food
var p2=new Person();
p2.eat()//->food,所以只要是Person的对象,他们都会共享原型对象的方法,当然,p1.name也会共享Person的实例属性,因为p1是Person的一个实例
好了,到这里原型的概念我们已经讲完了,大家或许会疑问,上面的new一个Person实例的过程中究竟发生了什么呢?为什么这个实例能够访问到原型对象中的方法?其实,在这个过程过程中,p1实例拥有了一个指针,这个指针指向构造函数的原型对象。此时原型对象中的方法自然能够被实例所访问。用一张图来说明下:
这里,我们总结下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象拥有一个指向构造函数的指针,而实例拥有一个指向原型对象的内部指针(这就是前面所提到的[[Prototype]],即__proto__,要注意的是这个__proto__属性在chrome浏览器中是可以看到的,而在大部分浏览器是隐藏的!)
二,关于原型链继承
好了,说了这么多终于到回到我们的主角了【原型链】,提出一个思考:如果我们让原型对象等于另外一个对象的实例,将会有一个什么样的结果呢?先看下面一段代码
function Person(){
this.name="bob";
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
Student.prototype=new Person();//将Person实例赋给Student的原型对象
var one=new Student();
one.name//bob
one.eat()//food,Student的实例能访问到Person对象的实例方法,也能访问到其原型属性中的方法
以上就是原型链继承的一种基本模式,那么我们怎么解释这样的原理呢?之前说过,对象的实例拥有一个指向原型对象的指针,那么student的原型对象拥有了Person对象实例后,自然也拥有一个指向Person原型对象的指针。此时,我们再new一个Student实例one时,one实例包含一个指向Student原型的指针,而Student.prototype拥有一个指向Person原型对象的指针,Person原型本身包含一个指向自身构造函数的指针。这样一来,就构成了实例与原型的链条。这就是所谓的原型链的概念!
用一张图描绘一下上面讲的情况:
大家要注意一下,这里的one对象的constructor现在指向谁呢?它并不指向Student,因为Student的原型指向另一个对象--Person的原型,而这个原型对象的constructor指向的是Person。
三,原型链方法的改写及注意的问题
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
//Student.prototype.eat=function(){
// return "food1";
//}
//注意如果更改原型语句的代码放在替换之前,那么下面one.eat()的结果将仍然是food
//,原因很简单,前面对prototype对象的修改,在后面的替换一句中被Person实例对象覆盖了
//,换句话说,就是现在的prototype实例中仍旧是以前的eat方法
Student.prototype=new Person();
Student.prototype.eat=function(){
return "food1";
}
var one=new Student();
console.log(one.eat());//food1
但是大家要注意一下一种情况,在通过原型链继承时,不能通过对象字面量个方式来更新原型对象
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){} Student.prototype=new Person();
Student.prototype={
run:function(){
return "run";
}
};
var one=new Student();
console.log(one.eat());//Uncaught TypeError: undefined is not a function
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){} Student.prototype=new Person();
Student.prototype.constructor=Student;//把Student原型对象中原本指向Person构造函数的对象强行指向到Student
var one=new Student();
console.log(one.eat());//food
从代码运行的情况来看,这个动作并没有切断原型链的继承,原因何在?
四,如何确定原型和实例关系
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){} Student.prototype=new Person();
Student.prototype.constructor=Student;
var one=new Student();
var person=new Person();
console.log(one instanceof Student);//true
console.log(one instanceof Person);//true
console.log(person instanceof Person);//true
console.log(person instanceof Student);//false
最后一个出现了false,什么原因,instanceof的工作原理是什么呢?
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){} Student.prototype=new Person(); var one=new Student();
var person=new Person();
console.log(Student.prototype.isPrototypeOf(one));//true
console.log(Person.prototype.isPrototypeOf(one));//true
console.log(Person.prototype.isPrototypeOf(person));//true
console.log(Student.prototype.isPrototypeOf(person));//false
五,总结
javascript中继承(一)-----原型链继承的个人理解的更多相关文章
- 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)
上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...
- JavaScript 随笔2 面向对象 原型链 继承
第六章 面向对象的程序设计 1.创建对象的几种方式 A)工厂模式 function CreatObj(name,sex,age){ this.name=name; this.sex=sex; this ...
- Typescript中的类 Es5中的类和静态方法和继承(原型链继承、对象冒充继承、原型链+对象冒充组合继承)
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...
- js继承之原型链继承
面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针, ...
- 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)
摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...
- 一篇JavaScript技术栈带你了解继承和原型链
作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...
- 深入浅出JavaScript之原型链&继承
Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...
- JS中原型链继承
当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...
- JavaScript之继承(原型链)
JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...
随机推荐
- Sublime Text 快捷键
ctrl+shift+t:重新打开最近关闭文件 快捷键 功能 ctrl+shift+n 打开新Sublime ctrl+shift+w 关闭Sublime,关闭所有打开文件 ctrl+shift+t ...
- [原]Python Web部署方式总结
不要让服务器裸奔 学过PHP的都了解,php的正式环境部署非常简单,改几个文件就OK,用FastCgi方式也是分分钟的事情.相比起来,Python在web应用上的部署就繁杂的多,主要是工具繁多,主流服 ...
- URL的语法及HTTP报文
大多数URL方案的URL语法都建立在这个由9部分构成的通用格式上: scheme://user:password@host:port/path;params?query#frag 方案:http或者h ...
- php输出utf-8格式
header("Content-type:text/html;charset=utf-8"); 输出数据前插入以上代码,以utf-8格式输出,避免乱码
- 自己一晚上总结的php基础知识!好累。好充实。
为了巩固自己的基础提升自己的技术.花了一晚上的时间结合w3c上的非常基础的东西,和自己的部分见解,写了不少,望大神们指正,指导.. <?php /* 这段话必须要写在开篇啊!死老猫,你又刺激我! ...
- 计算两条直线的交点(C#)
PS:从其他地方看到的源码是有问题的.下面是修正后的 /// <summary> /// 计算两条直线的交点 /// </summary> /// <param name ...
- ok6410的madplay配置
二.移植嵌入式播放器 madplay madplay 播放器程序主要依赖于如下库: zlib zlib-1.1.4.tar.gz 提供数据压缩用的函式库 libid3tag libid3tag- ...
- flask学习
安装环境: centos 6.3 python2.6 使用easy_install安装方式: [root@localhost ~]# easy_install flask 简单的hello from ...
- STM32单片机实现中断后不继续向下执行而是返回到main函数
做公司的一个项目,实现一个功能就是 机器在进行一项功能时(这项工作时间挺长),想要取消这项工作,重新选择.想了半天没想出来,结果同事提醒了一句,可以在程序中加一个外部中断,在中断中软件复位程序.用到以 ...
- [原创]PostgreSQL Plus Advanced Server监控工具PEM(二)
2.安装PEM Client 简单两条命令,开始PEM Client的安装. 我们在SUSE 11sp2上安装PEM Client 安装结束,运行PEM Client后可以看到如下的界面: 目前我们并 ...