当前位置: 首页 > news >正文

JS原型和原型链

文章目录

  • 深入面向对象
    • 1. 构造函数
    • 2. 原型
    • 3. constructor属性
    • 4. 对象原型(指向原型对象)
    • 5. 原型继承
    • 6. 原型链
    • 7. 构造函数应用
  • 学习总结


深入面向对象

面向对象编程(oop):灵活,代码可复用,容易维护和开发,适合多人合作的大型项目

特性:继承,封装,多态

img

1. 构造函数

JS通过构造函数实现封装 ,构造方法存在一个浪费内存的问题(存储复杂类型的时候)

img

如何解决?:原型

2. 原型

  1. 构造函数通过原型分配的函数是所有对象共享的
  2. JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象
  3. 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
  4. 我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
  5. 构造函数和原型对象中的this都指向实例化的对象
  6. 公共的属性写在构造函数里,公共的方法写在原型上
let that
function Student(name, price) {that=thisthis.name = name;this.price = price;}
console.log(Student.prototype)
//原型对象中的this指向实例对象
Student.prototype.setName = function (name) {console.log(this)this.name = name;
}
var s = new Student('Tom', 12);
// 构造函数中的this就是实例对象s
console.log(that===s)//True
s.setName()

Student.prototype:

img

 //this应用:封装一个求出的数组中最大最小值的方法Array.prototype.max = function(){return Math.max(...this)}const arr9 = [1, 2, 3]console.log(arr9.max())//3

3. constructor属性

  1. 每个原型对象里面都有一个constructor属性(constructor构造函数)
  2. 作用:该属性指向该原型对象的构造函数
  3. 如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象的内容,这样修改后的原型对象constructor就不再指向当前构造函数了,此时,我们可以在修改后的原型对象中,添加一个和constructor来指向原来的构造函数
 function Student(name, price) {this.name = name;this.price = price;}console.log(Student.prototype)// Student.prototype.sing = function () {//         console.log('I am singing')// }// Student.prototype.dance = function () {//         console.log('I am dancing')// }Student.prototype = {//还有让constructor重新指回原型对象的构造函数constructor: Student,sing: function () {console.log('I am singing')},dance: function () {console.log('I am dancing')}}var s = new Student('Tom', 12);console.log(Student.prototype.constructor === Student)//True

4. 对象原型(指向原型对象)

对象都会有一个属性:__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为有__proto__原型的存在

img

  1. __proto__是JS非标准属性
  2. [[prototype]]__proto__意义相同
  3. 用来表明当前实例对象指向哪个原型对象prototype
  4. __proto__对象原型里面也有一个constructor属性,指向创建该实例对象的构造函数
 Student.prototype = {//还有让constructor重新指回原型对象的构造函数constructor: Student,sing: function () {console.log('I am singing')},dance: function () {console.log('I am dancing')}}var s = new Student('Tom', 12);console.log(s)//对象原型__proto__指向构造函数的原型对象prototypeconsole.log(s.__proto__===Student.prototype)//true
//console.log(s.__proto__.constructor==Student)//trueconsole.log(Student.prototype.constructor === Student)//True

img

5. 原型继承

核心代码:子类的原型=new 父类()

 const Persons={eyes:2,head:1}function Women(){}//Women通过原型来继承PersonWomen.prototype=Persons;console.log(Women.prototype)//让原型对象上的constructor指回构造函数Women.prototype.constructor=Women;const red=new Women();console.log(red)console.log(red.__proto__)

img

上面的写法问题是Women和Men都共用一个prototype,要给Women的prototype上添加方法或属性时,Men也会同时拥有,但有时只想给Women添加,这时就需要用到构造函数,因为现在的需求是:结构相同,对象不同

function Persons() {this.eyes = 2;this.age = 13;}function Women() {}//直接使用new Person()创建一个新的对象,和Men的互不干扰Women.prototype = new Persons();//让原型和对象上的constructor指回构造函数Women.prototype.constructor = Women;Women.prototype.baby=function(){console.log('I am a baby')}const red = new Women();function Men() {}Men.prototype = new Persons();//让原型和对象上的constructor指回构造函数Men.prototype.constructor = Women;const green = new Men();

6. 原型链

  1. 只要是对象都有__proto__,指向构造函数的原型对象prototype
  2. 构造函数的原型对象也是一个对象,也有__proto__,指向的是Object的原型对象prototype
  3. 只要是原型对象,就有constructor,指回构造函数

img

原型链- 查找规则:

  1. 当访问一个对象的属性或方法时,首先查找这个对象自身有没有
  2. 如果没有就查找他的原型(也就是__proto__指向的prototype原型对象)
  3. 如果还没有就查找原型对象的原型(Object的原型对象)
  4. 以此类推一直找到Object(null)为止
  5. __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
  6. 可以使用instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链身上
        console.log(green instanceof Men)//trueconsole.log(green instanceof Persons)//trueconsole.log(green instanceof Object)//true

7. 构造函数应用

<body><button class="delete">删除</button><button class="login">登录</button><script>function Modal(title = '', message = '') {// 构造函数中创建属性要使用thisthis.modalBox = document.createElement('div')this.modalBox.className = 'modal'this.modalBox.innerHTML = `<div class="header">${title}</div><i>x</i><div class="body">${message}</div>`console.log(this.modalBox)}new Modal('温馨提示', '您没有权限进行删除操作')new Modal('友情提示', '您还未登录')//给构造函数原型挂载open方法Modal.prototype.open = function () {//判断页面中是否有盒子//有就移除const box = document.querySelector('.modal')box&&box.remove()document.body.append(this.modalBox)//盒子显示出来,就可以绑定关闭事件了//这个地方要使用箭头函数,因为this指向的是实例对象,如果用普通函数,this指的就是i标签,不是我们所期望的this.modalBox.querySelector('i').onclick = () => {this.close()}}//挂载close方法Modal.prototype.close = function () {this.modalBox.remove()}//点击删除按钮document.querySelector('.delete').addEventListener('click', function () {const del = new Modal('温馨提示', '您没有权限进行删除操作')del.open()})//点击登录按钮document.querySelector('.login').addEventListener('click', function () {const log = new Modal('友情提示', '您还未登录')log.open()})</script>
</body>

imgimg

学习总结

这周主要复习了JS高级相关的知识,但是还没复习完,下周把JS高级和ES6再复习复习

http://www.dtcms.com/a/572915.html

相关文章:

  • Rust 赋能图片批量处理:从 ImageKit 实现到行业前沿优化实践
  • ceph osd down排查
  • Android 14 系统启动流程深度解析:内置SD卡挂载流程
  • 【Qt】大数据量表格刷新优化--只刷新可见区域
  • 基于 React 的倒计时组件实现:暴露方法供父组件状态管理
  • 2.每日机器学习——张量(Tensors)
  • wordpress换php7出错内蒙古seo公司
  • 设计模式——桥接模式(bridge)
  • 阳光家园广州网站个人网站如何做即时支付
  • Arbess零基础学习 - 使用Arbess+GitLab实现.Net 项目构建/主机部署
  • 【数据结构】PriorityQueue优先队列:基于堆(heap)实现
  • PCB设计如何防止别人抄板?
  • macOS自定义安装PlatformIO Core
  • VSCode中Copilot的询问、编辑、代理有啥区别?
  • 二重积分器(Double Integrator)
  • APP与小程序分账系统是什么?资金管理新思路,合规高效分账
  • Hudi和Iceberg的Specification规范角度详细比较异同点
  • 临安网站建设杭州低价做网站
  • 肇庆市手机网站建设品牌专业做网站企业
  • 幂等性 VS 分布式锁:分布式系统一致性的两大护法 —— 从原理到实战的深度剖析
  • 初识DDD架构
  • 一次redis内存泄露故障分析
  • 计算机网络自顶向下方法32——网络层 网络层概述 转发和路由选择,数据平面和控制平面(传统方法,SDN方法) 网络服务模型
  • 深入理解MySQL_3 I/O成本
  • 哪个网站可以做验证码兼职gom传奇网站建设
  • 做网站一年能赚多少钱没有备案的网站怎么挂广告
  • vscode-ssh无法进入docker问题解决
  • iOS 应用网络权限弹窗的问题及解决方案
  • 使用 FastAPI 异步动态读取 Nacos 配置
  • 怀远做网站电话网站建设期末作业要求