JS学习笔记之原型链和利用原型实现继承详解


Posted in Javascript onMay 29, 2019

本文实例讲述了JS学习笔记之原型链和利用原型实现继承。分享给大家供大家参考,具体如下:

原型链

原型链是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的

实例对象中有__proto__,是对象,叫原型,不是标准的属性,浏览器使用,并且有的游览器不支持
构造函数中有prototype属性,也是对象,叫原型

注意 原型中的方法是可以互相访问的

实例代码

function Animal(name,age){
    this.name=name;
    thia.age=age;
   }

   //在原型中添加方法
   Animal.prototype.eat=function(){
    console.log("动物吃草")
    this.play()
   }
   Animal.prototype.play=function(){
    console.log("玩啥呢")
   }

原型的简单语法  

利用原型共享数据

第一种 写法

function Student(name,age,sex){
      this.name=name;
      this.age=age;
      this.sex=sex;
   }
  
   Student.prototype.height="188"
   Student.prototype.weight="55kg"
   Student.prototype.study=function(){
      console.log("好好学习i")
    }
  var stu=new Student("小红",20,"男")
  console.dir(stu)

结果

JS学习笔记之原型链和利用原型实现继承详解

第二种 写法

function Student(name,age,sex){
      this.name=name;
      this.age=age;
      this.sex=sex;
   }
  Student.prototype={
    height:"188",
    weight:"55kg",
    study:function(){
      console.log("好好学习i")
    }
   }
  var stu=new Student("小红",20,"男")
  console.dir(stu)

结果

JS学习笔记之原型链和利用原型实现继承详解

我们会发现 两种写法还是有差别的  ,第二种写法会导致constructor构造器属性消失 所以我们得手动修改构造器指向

最终代码

function Student(name,age,sex){
      this.name=name;
      this.age=age;
      this.sex=sex;
   }
  Student.prototype={
    constructor:Student,
    height:"188",
    weight:"55kg",
    study:function(){
      console.log("好好学习i")
    }
   }
  var stu=new Student("小红",20,"男")
  console.dir(stu)

好了,这回有了

JS学习笔记之原型链和利用原型实现继承详解

实例对象使用属性或方法的规则

实例对象使用的属性或方法,现在实例中查找,如果有则使用自身的属性或方法,
如果没有,则通过__proto__指向的原型对象 查找方法,找到则使用,
如果找不到则继续向__proto__寻找,直到未找到时报错

构造函数和实例对象和原型对象之间的关系

     构造函数可以实例化对象
     构造函数中有一个属性叫prototype,是构造函数的原型对象
     构造函数的原型对象(prototype)中有一个constructor 构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
     实例对象的原型对象(__proto__) 指向的是该构造函数的原型对象(prototype)
     构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问

改变原型是否可以改变?

首先我们得知道构造函数和实例对象中的this 指向的是什么

这里我创建了自定义构造函数 Person ,并在内部输出了this 

并且在Person 的原型对象上添加了一个eat 方法,也输出了一个this,

接着我实例化了一个对象,并调用eat方法,

我们执行一下,查看结果如何

JS学习笔记之原型链和利用原型实现继承详解

输出结果

JS学习笔记之原型链和利用原型实现继承详解

由此得出

原型对象中方法中的this 就是实例对象

构造函数中的this就是实例对象

接下来我们尝试改变一下原型的指向

JS学习笔记之原型链和利用原型实现继承详解

这段代码中,首先我定义了一个Person自定义构造函数,并且在原型上添加了一个eat方法

定义了一个Student 函数,在原型上定义了一个sayHi方法,

然后我将 Student的原型指向 了一个 Person的实例对象

接着实例化一个Student,接着分别在stu 实例上 尝试着调用 eat方法 和 sayHi 方法,

运行结果

JS学习笔记之原型链和利用原型实现继承详解

到此我们可以确定,stu实例对象原型指向被下面这条代码改变了

Student.prototype=new Person(10);

总结

原型指向可以被改变的

实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象

构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(__proto__)指向也会发生改变

实例对象和原型对象之间的关系是通过__proto__ 原型来联系起来的,这个关系就是原型链

如果原型指向改变了,那么就应该再原型改变指向之后添加原型方法

那么sayHi方法则会创建在 new Person(10) 这个实例对象上

原型最终指向了哪里

实例对象中的__proto__指向的是构造函数的prototype

以此代码为例

JS学习笔记之原型链和利用原型实现继承详解

测试一下

JS学习笔记之原型链和利用原型实现继承详解

JS学习笔记之原型链和利用原型实现继承详解

所以

per实例对象的__proto__ ---指向--->  Person.prototype的__proto__  ---指向--->  Object.prototype的__proto__ 是Null

查看了一下html的dom对象,这有很有意思的原型链

JS学习笔记之原型链和利用原型实现继承详解

这里祭出祖传JPG

JS学习笔记之原型链和利用原型实现继承详解

实现继承

小知识---->instanceof的判断方法:

从左边操作数的__proto__路线出发,从右边操作数的prototype出发,如果两条路线最终指向一个引用就是true了

1.利用 call 借用构造函数继承

优点:实现了继承属性,但值都不相同

缺点: 无法继承父级类别中原型上的方法

function Person(name,age,sex,weight){
  this.name=name;
  this.age=age;
  this.sex=sex;
  this.weight=weight;
}
Person.prototype.sayHi=function(){
  console.log("您好")
}

function Student(name,age,sex,weight,score){
  //将当前实例对象传入Person 借过来使用一次来达到继承效果
  Person.call(this,name,age,sex,weight);
  this.score=score;
}

var stu1=new Student("小明",10,"男","10kg","100")

2.  prototype 实现继承

利用prototype,将Student 的prototype 指向 Person 来达到继承效果,

优点:继承了父级原型上的方法

缺点:   实例化多个Student 都必须共用相同的name 和 age 

Student.prototype.constructor=Student

注意:   使用原型继承时,需要将构造器的指向更改回正确的指向

function Person(name,age){
    this.name=name;
    this.age=age;
   }

   Person.prototype.eat=function(){
    console.log("Person 吃饭")
   }

   function Student(num,score){
    this.num=num
    this.score=score
   }
   //继承
  Student.prototype=new Person("小红",10)
  Student.prototype.constructor=Student

  var stu =new Student(2016002288,80)

  stu.eat()//Person 吃饭

3.组合继承

组合继承其实就是结合了上述的两种方法来实现继承,拥有两种方法的优点

function Person(name,age,sex){
    this.name=name;
    this.age=age;
    this.sex=sex;
   }
   Person.prototype.sayHi=function(){
    console.log("你好")
   }

   function Student(name,age,sex,score){
    //借用构造函数
    Person.call(this,name,age,sex)
    this.score=score
   }

   // 改变了原型指向
   Student.prototype=new Person();//不传值
   Student.prototype.eat=function(){
    console.log("吃东西");
   }

   var stu=new Student("小黑",20,"男","100分")
   console.log(stu.name,stu.age,stu.sex,stu.score);
   stu.sayHi()//你好
   stu.eat()//吃东西

4.拷贝继承

类似于复制,把一个对象中的属性和方法直接复制到另一个对象中

function Person(){
  }

  Person.prototype.name="小红"
  Person.prototype.age=18

  function Student(){
  }
  
  var p=Person.prototype;
  var s=Student.prototype;

  for(key in p){
    s[key]=p[key]
  }

  console.dir(Student)

console

JS学习笔记之原型链和利用原型实现继承详解

每次都要for in 好累 ,  可以进行优化封装一下

function extend(Child,Parent) {


var p = Parent.prototype;


var c = Child.prototype;



for (var i in p) {



c[i] = p[i];



}
    
    //这个属性直接指向父对象的prototype属性,可以直接调用父对象的方法,为了实现继承的完备性,纯属备用性质


c.par = p;


}

5. 直接继承prototype

优点 : 效率比较高

缺点 : 因为相当于是个传址过程 所以修改Student的属性 Person 的也会被更改 

function Person(){};

  Person.prototype.name="小红";
  Person.prototype.age=18;

  function Student(){};

  Student.prototype=Person.prototype;

  console.dir(Student);
  console.dir(Person);
  Student.prototype.age=25;

console

JS学习笔记之原型链和利用原型实现继承详解

6.利用空对象作中介实现继承

用这种方式修改 Student 的prototype 不会影响到 Person的prototype

function Person(){};
  Person.prototype.name="小红";
  Person.prototype.age=11;

  function Student(){};
  var F=function(){};
  F.prototype=Person.prototype;

  Student.prototype=new F();
  Student.prototype.constructor=Student;

  Student.prototype.age=25;

  console.dir(Person)
  console.dir(Student)

console

JS学习笔记之原型链和利用原型实现继承详解

封装一下

function extend(Child,Parent) {


var F = function(){};



F.prototype = Parent.prototype;



Child.prototype = new F();



Child.prototype.constructor = Child;



Child.par = Parent.prototype;


}

更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
javascript 短路法代码精简
Aug 20 Javascript
JQuery与JSon实现的无刷新分页代码
Sep 13 Javascript
javaScript如何生成xmlhttp
Dec 16 Javascript
Javascript玩转继承(二)
May 08 Javascript
JavaScript实现更改网页背景与字体颜色的方法
Feb 02 Javascript
javascript获取select值的方法分析
Jul 02 Javascript
vue + element-ui实现简洁的导入导出功能
Dec 22 Javascript
为vue-router懒加载时下载js的过程中添加loading提示避免无响应问题
Apr 03 Javascript
详解elementui之el-image-viewer(图片查看器)
Aug 30 Javascript
Vue如何使用混合Mixins和插件开发详解
Feb 05 Javascript
vue-cli3使用mock数据的方法分析
Mar 16 Javascript
vue中路由跳转不计入history的操作
Sep 21 Javascript
vue读取本地的excel文件并显示在网页上方法示例
May 29 #Javascript
vue-cli3中vue.config.js配置教程详解
May 29 #Javascript
详解vue-cli3开发Chrome插件实践
May 29 #Javascript
vue里的data要用return返回的原因浅析
May 28 #Javascript
Vue+Element实现表格编辑、删除、以及新增行的最优方法
May 28 #Javascript
Javascript三种字符串连接方式及性能比较
May 28 #Javascript
vue+element实现表格新增、编辑、删除功能
May 28 #Javascript
You might like
web方式ftp
2006/10/09 PHP
php无限级评论嵌套实现代码
2018/04/18 PHP
PHP远程连接oracle数据库操作实现方法图文详解
2019/04/11 PHP
jQuery 1.3 和 Validation 验证插件1.5.1
2009/07/09 Javascript
JQuery AJAX提交中文乱码的解决方案
2010/07/02 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
2010/11/17 Javascript
jquery中prop()方法和attr()方法的区别浅析
2013/09/06 Javascript
利用JavaScript实现新闻滚动效果(实例代码)
2013/11/27 Javascript
js对象内部访问this修饰的成员函数示例
2014/04/27 Javascript
jquery实现点击弹出可放大居中及关闭的对话框(附demo源码下载)
2016/05/10 Javascript
JavaScript模板引擎Template.js使用详解
2016/12/15 Javascript
angular写一个列表的选择全选交互组件的示例
2018/01/22 Javascript
Vue实现左右菜单联动实现代码
2018/08/12 Javascript
详解Axios 如何取消已发送的请求
2018/10/20 Javascript
微信小程序实现渐入渐出动画效果
2019/06/13 Javascript
Vue中Table组件行内右键菜单实现方法(基于 vue + AntDesign)
2019/11/21 Javascript
JavaScript计算正方形面积
2019/11/26 Javascript
详解为什么Vue中不要用index作为key(diff算法)
2020/04/04 Javascript
[31:00]2014 DOTA2华西杯精英邀请赛5 24 NewBee VS iG
2014/05/25 DOTA
[01:25:09]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第二场
2014/05/24 DOTA
[50:44]DOTA2-DPC中国联赛 正赛 SAG vs Dragon BO3 第二场 2月22日
2021/03/11 DOTA
对pandas的dataframe绘图并保存的实现方法
2017/08/05 Python
python中pytest收集用例规则与运行指定用例详解
2019/06/27 Python
python判断无向图环是否存在的示例
2019/11/22 Python
关于Numpy中的行向量和列向量详解
2019/11/30 Python
Python实现序列化及csv文件读取
2020/01/19 Python
python 实现字符串下标的输出功能
2020/02/13 Python
使用python处理题库表格并转化为word形式的实现
2020/04/14 Python
为什么python比较流行
2020/06/19 Python
Python通过类的组合模拟街道红绿灯
2020/09/16 Python
利用python绘制正态分布曲线
2021/01/04 Python
2015年第十五个全民国防教育日宣传活动方案
2015/05/06 职场文书
2015年小学总务工作总结
2015/07/21 职场文书
PyQt5 QThread倒计时功能的实现代码
2021/04/02 Python
Python字符串常规操作小结
2022/04/03 Python
Docker容器harbor私有仓库部署和管理
2022/08/05 Servers