FE_JS对象的理解

news2024/11/24 6:55:25

对象是JS中的引用数据类型,对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性。使用typeof检查一个对象时,会返回object。

1 对象创建模式 - Object构造函数模式

套路: 先创建空Object对象, 再动态添加属性/方法
适用场景: 起始时不确定对象内部数据
问题: 语句太多

<script>
    var p = new Object();
    p.name = 'zhaoshuai-lc'
    p.age = 27
    p.setName = function (name) {
        this.name = name
    }
    console.log(p);
    p.setName('zhaoshuai-la')
    console.log(p);

</script>

在这里插入图片描述但是,引出一下问题:
在这里插入图片描述
为什么?箭头函数就出现了问题,这里涉及到的是箭头函数的问题:
对于箭头函数而言:this —> window
在这里插入图片描述
对于普通函数而言:this—>p
在这里插入图片描述

2 对象创建模式-对象字面量模式

套路: 使用{}创建对象, 同时指定属性/方法
适用场景: 起始时对象内部数据是确定的
问题: 如果创建多个对象, 有重复代码

<script>
    var p = {
        name: 'zhaoshuai-lc',
        age: 27,
        sex: 'male'
    }
    console.log(p);
</script>

在这里插入图片描述

3 对象创建模式-自定义构造函数模式

套路: 自定义构造函数, 通过new创建对象
适用场景: 需要创建多个类型确定的对象
问题: 每个对象都有相同的数据, 浪费内存
在这里插入图片描述

4 对象创建模式-构造函数+原型的组合模式

构造函数+原型的组合模式–>最好用这个写法
套路: 自定义构造函数, 属性在函数中初始化, 方法添加到原型上
适用场景: 需要创建多个类型确定的对象
放在原型上可以节省空间(只需要加载一遍方法)

在这里插入图片描述

4 对象的继承

4.1 prototype 的引入

由于直接 new 出来的实例对象,都有自己的属性和方法的副本,无法做到数据共享,也浪费了内存。考虑到这点,Brendan Eich 决定为构造函数设置一个 prototype 属性。将所有需要共享的属性和方法,都放在这个 prototype 对象里面;那些独有的属性和方法,就放在构造函数里面。
这样实例对象创建好之后,将会有两类属性和方法,一个是自己的,一个是通过原型链(沿着 prototype )查找到的。

继承就是子类可以使用父类的所有功能,并且对这些功能进行扩展。 比如构造函数 B 想要使用构造函数 A 里的属性和函数,一种是直接复写 A 里的代码,复制粘贴一下。还有一种就是使用继承,让 B 继承 A,这样 B 就可以使用 A 里的功能。

4.2 原型链继承

将子类的原型对象指向父类的实例。

Child.prototype = new Parent()
function Parent(name, gender) {
    this.name = name;
    this.gender = gender;
}

Parent.prototype.getInfo = function () {
    console.log('my name is ' + this.name + '; I am a ' + this.gender)
}

function Child(age) {
    this.age = age
}
Child.prototype.getChildInfo = function () {
    console.log('i am child')
}
// 将子类的原型对象指向父类的实例。
Child.prototype = new Parent("parent", "boy")
var child1 = new Child(30)
console.log(child1) // Child {age:30}
child1.getInfo() // my name is parent; I am a boy
console.log(child1.name) // parent

child1.getChildInfo() // TypeError: child1.getChildInfo is not a function

  1. 默认 Child 实例的原型对象是指向 Child.prototype 的,经过
Child.prototype = new Parent("parent","boy")

Child 的原型对象就指向了 Parent 的实例,具体原型链图如下:
在这里插入图片描述
依图可得,child 实例 _proto_ 属性指向 parent 实例, parent 实例下的 _proto_ 属性指向 Parent.prototype。所以 child1 既可以访问到 parent 实例的属性和方法(即 Parent 构造函数中定义的),也可以访问到 Parent.prototype 上定义的属性和方法

function Parent(name, gender) {
    this.name = name;
    this.gender = gender;
    this.colors = ["blue", "pink"] // 新增引用类型属性 colors
}

Parent.prototype.getInfo = function () {
    console.info('my name is ' + this.name + '; I am a ' + this.gender)
}

function Child(age) {
    this.age = age
    this.sports = ["basketball"]  // 新增引用类型属性 sports
}

var parent = new Parent("parent", "boy")
Child.prototype = parent
var child1 = new Child(30, "child1 name") // 想传入child1 name 作为该实例独有的名称
child1.gender = "girl"
child1.colors.push("green")
child1.sports.push("football")
console.info(child1) // Child {age: 30, sports: ["basketball", "football"], gender: "girl"}
console.log(child1.name) // parent

var child2 = new Child(29, "child2 name") // 想传入child2 name 作为该实例独有的名称
console.info(child2) // Child {age: 29, sports: ["basketball"]}
console.info(child2.colors) //  ["blue", "pink", "green"]

优点:

  • 继承了父类构造函数里的属性和方法,又继承了父类原型对象上的属性和方法

缺点:

  • 无法实现多继承(因为指定了原型对象)
  • 来自原型对象的所有属性都被共享了,当更改个引用类型的属性时,所有的实例对象都会受到影响(这点从child2.colors可以看出来)
  • 无法传递参数给父对象,比如我要设置个独有的 name 值,就只能在自己的构造函数里重新定义 name 属性,用来屏蔽父对象的name(这点从child1.name可以看出来)

4.3 构造函数继承

在子类构造函数内部使用 call 或 apply 来调用父类构造函数

function Child() {
	Parent.call(this,...arguments)
}

来达到增强子类的目的,等于复制父类的实例属性给子类

function Parent(name,gender) {
	this.name = name;
	this.gender = gender;
}
function Child(age,name,gender) {
	this.age = age
	Parent.call(this,name,gender) // 等价于Parent.apply(this,[name,gender])
}
var child1 = new Child(30,"child1 name","girl")
console.info(child1) // Child {age: 30, name: "child1 name", gender: "girl"}
console.info(child1.name) // child1 name
console.info(child1 instanceof Child) // true
console.info(child1 instanceof Parent) // false

  • 相当于在子类构造函数里,直接执行了父类构造函数。执行完后就会在子类的构造函数新增了父类所有的属性。
  • 这个继承是借用了 call 或 apply 函数的能力。
  • Child 的实例跟 Parent之间并无联系(这点从 intanceof Parent 可以看出来)

优点:

  • 可以有多继承(在子类构造函数里分别调用父类的构造函数即可)
  • 解决了子类实例共享父类构造函数里引用类型属性的问题(这点从 child.colors 可以看出来)
  • 可以向父类传递参数(这点从 child1.name 可以看出来)

缺点:

  • 不能继承父类原型对象上的属性和方法
  • 子类实例跟父类之间并无联系(这点从 child1 instanceof Parent 为 false 可以看出来)
  • 无法实现函数复用,对于父类里的函数属性,每个子类都会复制一份,影响性能

4.4 组合继承

既然原型链继承跟构造函数继承分别有优缺点,那能否将这两者结合起来?

// 原型链继承
Child.prototype = new Parent()
// 构造函数继承
function Child() {
	Parent.call(this,...arguments)
}

  • 使用原型链继承来保证子类能够继承父类原型对象上的属性和方法
  • 使用构造函数继承来保证子类能够继承到父类构造函数上的属性和方法

基操:

  • 通过call/apply在子类构造函数内部调用父类构造函数
  • 将子类构造函数的原型对象指向父类构造函数创建的一个匿名实例
  • 修正子类构造函数原型对象的constructor属性,将它指向子类构造函数
function Parent(name) {
    this.name = name;
}

Parent.prototype.getInfo = function () {
    console.info('my name is ' + this.name)
}

function Child(name) {
    Parent.call(this, name) // 构造函数继承
}

Child.prototype.getChildInfo = function () {
    console.log('i am child')
}

Child.prototype = new Parent() // 原型链继承,传入空参数即可,因为传入任何参数都会被屏蔽
Child.prototype.constructor = Child // 修复 child1 constructor 指向 Parent 问题

var child1 = new Child("child1 name")
child1.getChildInfo() // TypeError: child1.getChildInfo is not a function

console.info(child1) // Child {name: "child1 name"}
child1.getInfo() // my name is child1 name
console.info(child1.constructor) //ƒ Child(name) { Parent.call(this,name) // 构造函数继承 }


在这里插入图片描述
优点:

  • 可以继承父类实例属性和方法,也可以继承父类原型对象上的属性和方法
  • 跟构造函数继承一样,解决了父类构造函数里引用类型属性共享问题
  • 跟构造函数继承一样,可以向父级传递参数

那这个组合继承是不是完美的呢?答案是否定的,接下来一探究竟

function Parent(name) {
    console.info(name)
    this.name = name
}

function Child(name) {
    Parent.call(this, name)
}

Child.prototype = new Parent() // undefined
Child.prototype.constructor = Child

var child1 = new Child('child1') // child1
console.info(child1) // Child { name: 'child1' }
console.info(Child.prototype) // Parent { name: undefined, constructor: [Function: Child] }

  • 由于 new Parent 时会调用一次 Parent 函数,此时 name 为 undefined; 而在 Child构造函数里也会调用次 Parent 函数,并传入 child1 作为 name 参数
  • Child.prototype 是指向 Parent 实例对象,这个实例的 name 为 undefined, constructor
    重新设置为 Child 了
  • 调用了两次父类的构造函数
  • 子类实例中的属性和方法会屏蔽父类实例上的属性和方法,增加了不必要的内存

5 class 继承 【重点】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/535252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode: 1335. 工作计划的最低难度 | 暴力递归=>记忆化搜索=>动态规划 】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

又一个开源便斩获 7k star 的新模型「GitHub 热点速览」

作者&#xff1a;HelloGitHub-小鱼干 Star 并不能代表什么&#xff0c;但是绝对能表示一个项目的受欢迎程度。就像刚开源一周就有 7k star 的新模型&#xff0c;输入文本 / 图像就能获得 3D 对象。除了这个新模型&#xff0c;本周还有一款新的 Web 3D 渲染引擎 Orillusion&…

MySQL学习---17、MySQL8其它新特性

1、MySQL新增特性 1.1 更简便的NoSQL支持 NoSQL泛指非关系型数据库和数据存储。随着互联网平台的规模飞速发展&#xff0c;传统的关系型数据库已经越来越不能瞒住需求。从5.6版本开始&#xff0c;MySQL就开始支持简单的NoSQL存储功能。MySQL 8对这一功能做了优化&#xff0c;…

阿里P8强烈推荐的可伸缩服务架构:框架与中间件笔记

随着企业业务量的增加&#xff0c;流量洪峰在不断挑战着业务系统的承载能力&#xff0c;设计高并发、可伸缩的系统已成为软件架构师的紧迫任务&#xff0c;而分布式、可伸缩的架构模式已成为抵御洪峰的有效方案之一。本书汇集了作者在多年核心系统开发中的架构及实践经验&#…

【算法】--- 几分钟带你走进排序算法大门(上)

文章目录 前言&#x1f31f;一、常见的排序算法&#xff1a;&#x1f31f;二、直接插入排序排序&#xff1a;&#x1f4d2;2.1 基本思想&#xff1a;&#x1f4d2;2.2 代码&#xff1a;&#x1f4d2;2.3 时间复杂度&#xff1a;O(N^2)&#x1f4d2;2.4 流程图详解&#xff1a; …

聚观早报 | Midjourney官方在QQ开启内测;富士康印度新工厂动工

今日要闻&#xff1a;Midjourney官方在QQ开启内测&#xff1b;富士康印度新工厂动工&#xff1b;闲鱼将开收软件服务费&#xff1b;专家建议五年内禁售燃油车&#xff1b;笑果文化已被立案调查 Midjourney官方在QQ开启内测 5 月 15 日&#xff0c;据 Midjourney AI 微信公众号…

Unity之OpenXR+XR Interaction Toolkit实现 手枪模型的拆卸和组装

前言 之前我们曾实现过PC端的模型的拆卸和组装&#xff0c;如果使用VR模式来实现物体的拆卸呢&#xff1f;如何使用双手手柄来控制物体&#xff0c;拆卸物体呢&#xff1f;今天我们就来实现一个VR小Demo&#xff0c;基于OpenXR &#xff0c;XR Interaction Toolkit插件来实现。…

程序员面试宝典

前言 编者: 大淘宝技术开发工程师 / 刘苏宏(淘苏) 淘苏(花名)目前是大淘宝技术的一名开发工程师。从国企 跳槽来到互联网&#xff0c;【职业规划】是他被问得最多&#xff0c;也思考得 最多的问题。 扫一扫&#xff0c;关注公众号【大淘宝技术】 了解更多大淘宝技术干货沉淀 …

技术架构演进之路-Docker【一】

技术架构演进之路 了解每种技术架构以及如何演进的&#xff0c;熟悉Docker在架构中的核心作用 八大架构演进 单机架构 当前服务由应用服务和数据库服务两个服务组成&#xff0c;应用服务由 用户模块、商品模块、交易模块三个模块组成&#xff0c;我们可以理解它为 淘宝。用户模…

互联网时代,自媒体宣发的概念、优势、策略及注意事项

自媒体宣发是指通过自己或者委托专业机构&#xff0c;运用自媒体平台传播宣传信息的一种方式。在互联网时代&#xff0c;自媒体已经成为了企业推广的一种重要手段。本文将为大家介绍自媒体宣发的概念、优势、策略及注意事项。#自媒体# 一、什么是自媒体宣发&#xff1f; 自媒体…

通配符SSL证书是什么?

通配符SSL证书可以对申请的域名保护以外&#xff0c;还可以对下一级子域名无限使用&#xff0c;适合存在很多二级域名项目的网站&#xff0c;这样不需要额外对子域名申请SSL证书&#xff0c;还可以进行同意管理及部署SSL证书避免跨站窜站的问题。 申请通配符SSL证书 一、申请通…

SSH远程终端神器,你在用哪一款

唠嗑部分 在我们日常开发中啊&#xff0c;不可避免的要与Linux打交道&#xff0c;虽然我们作为开发&#xff0c;不要求我们对Linux有多么的专业&#xff0c;但是基本的操作还是要会的&#xff0c;举几个常用的例子&#xff1a; 1、查看nginx配置&#xff0c;配置转发 2、清理…

蓝桥杯模块学习4——数码管

第一章 硬件部分 1.1 电路的组成部分 1.1.1 译码器和锁存器 具体可回顾之前LED灯的文章&#xff1a; https://blog.csdn.net/weixin_63568691/article/details/130660096 1.1.2 共阳极数码管&#xff1a; 原理图&#xff1a; 功能&#xff1a; &#xff08;1&#xff09;可…

[网鼎杯 2020 青龙组]bang 复现--frida-dexdump安卓脱壳工具的使用

一.前言 在NSSCTF练习安卓逆向,第一次遇到安卓脱壳题 大佬的题解只有一句话"frida-dexdump一把嗦" 听起来容易做起来难,还遇到了安卓虚拟机的玄学bug,折磨了我很久,好在最终使用真机成功dump并得到flag 题目来源:[网鼎杯 2020 青龙组]bang 如果直接用jadx打开会发现…

重大喜讯!国产讯飞星火大模型将超越chatGPT!

引言 近年来&#xff0c;随着人工智能技术的快速发展&#xff0c;自然语言处理成为了研究的热点。而在自然语言处理领域&#xff0c;ChatGPT是一个备受关注的模型&#xff0c;它的出现极大地推动了自然语言处理技术的发展。然而&#xff0c;最近国内一家公司——讯飞&#xff0…

记录--10个超级实用的Set、Map使用技巧

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 Set是一种类似于数组的数据结构&#xff0c;但是它的值是唯一的&#xff0c;即Set中的每个值只会出现一次。Set对象的实例可以用于存储任何类型的唯一值&#xff0c;从而使它们非常适用于去重。 Map是…

如何为研发团队打造专属的效能提升路径|QECon 演讲回顾

近日&#xff0c;ONES 受邀参加 2023 QECon 全球软件质量&效能大会&#xff08;深圳站&#xff09;。在会上&#xff0c;ONES 研发效能改进咨询顾问陈仪&#xff0c;发表了主题为《如何为研发团队打造专属的效能提升路径》的演讲。 陈仪有着丰富的咨询经验&#xff0c;曾带…

C++考试

文章目录 1.程序填空1.1函数调用1.2前置和后置“”、“--”运算符重载1.3异常处理1.4文本文件读取 2.程序阅读2.1C编程基础2.2继承与派生2.3静态成员2.4继承与派生2.5 输入输出2.6 模板 3.程序改错3.1三种访问权限3.2 友元3.3抽象类不能实例化对象3.4常数据成员初始化必须使用构…

面试题总结

1、0513 1.重载和重写的区别? 重载发生在同一类中&#xff0c;同名的方法如果有不同的参数列表&#xff08;类型不同、个数不同、顺序不同&#xff09;则视为重载。 重写发生在父子类中&#xff0c;重写要求子类重写之后的方法与父类被重写方法有相同的返回类型&#xff0c;比…

Linux:在VMware中,如果虚拟机之前可以上网,之后突然不能上网,怎么办?

Linux系统版本&#xff1a;centos 7.5 x64位 VMware版本&#xff1a; VMware Workstation Pro 16 文章目录 前言一、什么原因会导致这种问题并如何解决它&#xff1f;原因①&#xff1a;虚拟机没有启动网络服务原因②&#xff1a;外部主机上VMware的【VMware NAT Service】服务…