原型链

原型链是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__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)

结果

第二种 写法

 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)

结果

我们会发现 两种写法还是有差别的  ,第二种写法会导致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)

好了,这回有了

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

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

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

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

    

改变原型是否可以改变?

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

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

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

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

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

输出结果

由此得出
原型对象中方法中的this 就是实例对象

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

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

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

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

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

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

运行结果

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

Student.prototype=new Person(10);

总结

原型指向可以被改变的

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

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

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

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

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

原型最终指向了哪里

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

以此代码为例


测试一下


所以

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

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


这里祭出祖传JPG

实现继承

小知识---->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=numthis.score=score}//继承Student.prototype=new Person("小红",10)Student.prototype.constructor=Studentvar 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=18function Student(){}var p=Person.prototype;var s=Student.prototype;for(key in p){s[key]=p[key]}console.dir(Student)

console

每次都要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

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

封装一下

function extend(Child,Parent) {var F = function(){};F.prototype = Parent.prototype;Child.prototype = new F();Child.prototype.constructor = Child;Child.par = Parent.prototype;}

JS学习笔记 原型链和利用原型实现继承相关推荐

  1. JS学习笔记17-面向对象编程-原型

    文章目录 一.面向对象 二.第一个面向对象程序 2.1 工厂模式 2.2 工厂模式的缺点 2.2.1 没有new , 2.2.2 函数重复调用 2.3 prototype(原型): 2.4 类(模子) ...

  2. Vue.js学习笔记—shop-bus:实战:利用计算属性、指令等知识开发购物车

    参考<Vue,js>实战(梁灏编著) shop-bus:实战:利用计算属性.指令等知识开发购物车 git代码地址 index.html <!DOCTYPE html> < ...

  3. sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map)

    sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map) 这几天学习和查看了jQuery和Property这两个很流行的前端库的御用选择器组件Sizzle.js的源代码,收获还是相对多的!之 ...

  4. javascript从入门到跑路-----小文的js学习笔记(25)------运动框架----匀速运动、缓冲运动、多物体运动、链式运动

    ** javascript从入门到跑路-----小文的js学习笔记(1)---------script.alert.document.write() 和 console.log 标签 javascri ...

  5. javascript从入门到跑路-----小文的js学习笔记目录

    ** javascript从入门到跑路-----小文的js学习笔记(1)---------script.alert.document.write() 和 console.log 标签 javascri ...

  6. JS学习笔记——入门基础知识总结

    JS入门基础知识总结1 前言 基础背景知识 一.产生历史: 二.特点: 三.应用方向: 四.Javascript组成: JavaScript书写使用方式 一.行内式(了解即可,项目中不使用,日常练习尽 ...

  7. node.js学习笔记5——核心模块1

    node.js学习笔记5--核心模块1 Node.js核心模块主要内容包括:(1)全局对象 (2)常用工具 (3)事件机制 (4)文件系统访问 (5)HTTP服务器与客户端 一: 全局对象 Node. ...

  8. ArcGIS JS 学习笔记4 实现地图联动

    原文:ArcGIS JS 学习笔记4 实现地图联动 1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而 ...

  9. Vue.js学习笔记 2022 04 17

    Vue.js学习笔记 1 Vue.js基础 Vue.js介绍 vuejs 渐进式 JavaScript 框架 Vue.js 如何应用 1 在普通html项目中,引入VUE.JS Hb 的项目 生成的 ...

最新文章

  1. 无人驾驶汽车系统入门:基于深度学习的实时激光雷达点云目标检测及ROS实现...
  2. windows7访问03文件服务器慢
  3. 数据结构(python语言)目录链接
  4. 基于ARM+DSP进行应用开发-经验共享
  5. UML的奥妙 - 学习UML笔记(1)
  6. vue 页面引入多个内部js_.html多页页面引入vue.js怎么开发?
  7. ide 两个模块的jdk版本不一样_Java平台模块系统(3)- JDK工具
  8. NLP情感分析笔记(二):Updated情感分析
  9. java打印等腰三角形_可打印丨四年级数学易错易失分的26个知识点总结(附例题+答案),给孩子收藏!...
  10. 【语音合成】基于matlab GUI语音合成【含Matlab源码 293期】
  11. java 16进制转字符串 乱码_Java中16进制与字符串之间的相互转换
  12. Excel中Alt快捷键的用法
  13. 以前的我“我是废物...”,现在的我“我是废物o(* ̄︶ ̄*)o” 2020.11.27日记
  14. Cookie中path总结
  15. 什么是网络智能运维?如何保障业务7x24小时在线?
  16. 【观察】美达电器:以数字化重塑质量管理体系,构筑车企新“护城河”
  17. 用友NC 财务核算账簿启用时 提示选中的科目表不是当前集团的账簿类型对应科目体系下的政策性科目表或其派生的科目表
  18. CSP 201803-4 棋局评估
  19. Python爬虫爬取百度贴吧的帖子
  20. 地理围栏算法解析(Geo-fencing)

热门文章

  1. 怎么取消苹果手机自动续费_苹果手机被订阅自动续费了怎么办 苹果退款
  2. 记一次短链系统设计:
  3. js判断时间是早上还是下午_JS获取时间显示上午,下午 | 学步园
  4. java时钟日历_java日历时钟小程序
  5. php如何获取手机序列号,基于php的苹果序列号查询接口调用代码实例
  6. c++ primer 第五版 翻译 第三章
  7. vscode2019使用教程_vs2019安装和使用教程(详细)
  8. word 文档结构图乱的解决方法
  9. 您的访问可能会对网站造成危险,已被腾讯云安全拦截
  10. 创建和编辑AutoCAD对象(VBApython)