JavaScript 高级程序设计 - 第 8 章 理解对象 学习笔记

news2025/4/17 7:58:20

JavaScript 高级程序设计 - 第 8 章 理解对象 学习笔记

本章内容量挺大的,因此笔记的话我也会分成 3-4 个部分去写,想要理解的细一点,顺便之后回顾的时候不会看的套类。

本章主要就是了解一下和理解一下什么是对象,包括 Object 上的 properties 和 mixin。

在 JavaScript 中,所有的存在(除了 primitive value)之外,都是对象,通常意义上来说,创建对象的方式有两种:

const person = new Object();
person.name = 'John';
person.age = 28;
person.sayHi = function () {
  console.log(`Hello from ${this.name}`);
};

const person2 = {
  name: 'Alex',
  age: 18,
  sayHi: function () {
    console.log(`Hello from ${this.name}`);
  },
};

二者在实现上没有什么区别,只是后者使用 object literal(对象字面量)更加的方便简洁。

attributes of property

以上面的实现为例,name, agesayHiperson 的 数据属性(data properties),并且同样也可以使用 Object.defineProperty() 的方法去赋值,如:

const person2 = {
  name: 'Alex',
  age: 18,
  sayHi: function () {
    console.log(`Hello from ${this.name}`);
  },
};

Object.defineProperty(person2, 'greet', {
  value: function () {
    console.log('Hello from the other side');
  },
});

person2.greet();

在这里插入图片描述

defineProperty 中传的第三个值,就是该 property 的 attributes。

interface PropertyDescriptor {
    configurable?: boolean;
    enumerable?: boolean;
    value?: any;
    writable?: boolean;
    get?(): any;
    set?(v: any): void;
}

/**
 * Marker for contextual 'this' type
 */
interface ThisType<T> { }

defineProperty<T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>): T;

PropertyDescriptor 中包含的,就是所有可能存在的属性,现在的规范是使用中括号括起来,如 [[Configurable]],不过说的都是一个东西。

  • value

    value 为 property 实际的值

  • writable

    person2.name = 'John';
    Object.defineProperty(person2, 'name', {
      writable: false,
    });
    
    console.log(person2.name);
    person2.name = 'Dick';
    console.log(person2.name);
    
    Object.defineProperty(person2, 'name', {
      writable: true,
      value: 'Rewritten',
    });
    
    console.log(person.name);
    

    结果如下:

    在这里插入图片描述

    可以看到,当 writable 设置为 false 之后,重新对 property 赋值也不无法对其进行修改。就算是之后重新修改 writable 也不行

    非严格模式下这样的执行会被忽略,严格模式下这么做会报错

  • configurable

    configurable 是一个 boolean,当一个属性的 configurable 被设置成 false,意味着当前的属性无法被使用 defineProperty 被重新定义、无法被删除、无法修改 configurable, enumerablewritable

    如果 writable 的值为 true,那么 value 还是可以被修改的,否则这个对象就被彻底 freeze,再也无法修改。

    Object.defineProperty(person2, 'age', {
      configurable: false,
      writable: false,
    });
    
    Object.defineProperty(person2, 'age', {
      enumerable: false,
    });
    

    在这里插入图片描述

    顺便,Object.freeze() 等同于将 configurablewritable 设为 false。

  • enumerable

    这个 attribute 代表了当前属性是否会出现在 for...in

    for (const key in person2) {
      console.log(key);
    }
    
    Object.defineProperty(person2, 'name', {
      enumerable: false,
    });
    
    for (const key in person2) {
      console.log(key);
    }
    

    在这里插入图片描述

  • get

    getter 是另一个相对而言比较新的内容,它主要的目的就是为了处理一些返回值,比如:

    const person2 = {
      _id: 1,
      name: 'Alex',
      age: 18,
      sayHi: function () {
        console.log(`Hello from ${this.name}`);
      },
      get id() {
        return `id is: ${this._id}`;
      },
    };
    
    console.log(person2.id);
    

    在这里插入图片描述

    这个案例中,person2 没有直接声明 id property,但是可以通过 getter 返回一个 id property,其原因在于,它的具体实现为:

    const person = new Object();
    person.name = 'John';
    person.age = 28;
    person._id = 2;
    person.sayHi = function () {
      console.log(`Hello from ${this.name}`);
    };
    
    Object.defineProperty(person, 'id', {
      get: function () {
        return this._id;
      },
    });
    
    console.log(person.id);
    

    在这里插入图片描述

    使用 getter 还有另一个原因,放到下面 setter 一起说。

  • set

    setter 的作用和 getter 相似,其用法如下:

    const person2 = {
      _id: 1,
      name: 'Alex',
      age: 18,
      sayHi: function () {
        console.log(`Hello from ${this.name}`);
      },
      get id() {
        return `id is: ${this._id}`;
      },
      /**
       * @param {string} arg
       */
      set realName(arg) {
        this.name = 'my name is: ' + arg;
      },
    };
    

    在这里插入图片描述

    同样也可以用 defineProperty 去实现。

    JS 中出现 getter 和 setter 的另一个原因就在于,ES6 之前 JS 中是没有私有属性的。于是社区约定俗成了一个规范,就是在 property name 中添加 _ 代表不应该被访问的私有属性,要去访问和修改这个私有属性,就需要通过 getter 和 setter 去实现。这样实际保存值的 property,即 this.__privateValue,就不会直接被用户所访问。

定义的方法为 defineProperty,获取 properties 的方法有两个:Object.getOwnPropertyDescriptor()Object.getOwnPropertyDescriptors()。前者需要知道 property 的名称,后者则会直接返回当前对象上的 properties。

console.log(Object.getOwnPropertyDescriptor(person2, 'name'));
console.log(Object.getOwnPropertyDescriptors(person2));

在这里插入图片描述

mixin

mixin 是一个被提到很多次的 concept,如果找一下的话,会发现 vue、scss 等都会发现直接有 mixin 这一属性或是函数。

ES6 也提供了 Object.assign() 的静态方法,它会遍历接收到的参数,然后将参数中所有可枚举 (Object.propertyIsEnumerable()true 的 properties) 和 自由(Object.hasOwnProperty()true 的 properties) 复制到目标属性上。

这可以很方便的实现 mixin,以下面代码为例:

const writeFile = {
  write: function () {
    console.log('Assume I can read file.');
  },
};

const scanFile = {
  scan: function () {
    console.log('Assume I can scan file');
  },
};

const readWriter = Object.assign({}, readFile, writeFile);
console.log(readWriter);

readFile.read();

const readWriterScanner = Object.assign({}, readWriter, scanFile);
readWriterScanner.scan();

在这里插入图片描述

可以看到,使用 mixin 提供更加灵活的语法,并且直接地满足了 SOLID 中的 single responsibility principle 和 interface segregation principle 两条原则。

liskov substitution principle 的判定我觉得稍微有点麻烦,逻辑上来说它要满足的事子类和父类,实现上来说 Object.assign() 完成了 shallow copy……

因为 JS 没有办法提供很好的静态检查,因此当使用 mixin 还会有其他的一些问题,如属性被重写的问题,依旧用上面的分代码为例,这里添加一点新的实现:

const fileOperator = {
  read: function () {
    console.log('I read file randomly.');
  },
  scan: function () {
    throw new Error('scan file fail.');
  },
};

const errorFileOperator = Object.assign({}, scanFile, fileOperator);
errorFileOperator.scan();

可以看到,在这个 mixin 中,scanfileOperator 重写了,所以这里的输出结果不是做一个 log,而是抛出异常:

在这里插入图片描述

搭配上 JS 中不存在的类型见擦,当项目规模比较大的情况下,尤其是出现 mixin 套用 mixin 的情况,property 的管理会成为一个比较麻烦的事情。

顺便,只是针对 Object.assign() 的话,它是没有回滚的概念的,也就是说,如果操作中出现一些异常,可能会出现一个部分实现复制的新对象。

总结一下 mixin 的优点和缺点。

优点:

  • 提高代码的复用性

  • 提高代码的灵活性

  • 模块化

  • composition over inheritance

    这是一个 OOP 常用的概念,组成偏向于继承,这样可以做到比较轻松的修改组成部分的代码,而不用担心影响到继承部分的功能

缺点:

  • 命名冲突

    假设说多个对象中都存在 id 这个属性,那么 JS 就无法 capture 这个问题

  • 排序很重要

    假设说多个对象中都存在 id 这个属性,那么最后一个 id 将会重写其他的 id

  • 直接依赖

    就不太像 spring 一样下面有底层的 DI 管理,很多时候要实现 mixin 还是得手动 cv,这样就会造成直接依赖(必须要知道对象,才能够实现 assign)

  • 提高代码复杂性

reference

  • Object.freeze()

  • SOLID,面向对象设计五大基本原则

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

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

相关文章

一文读懂DEM数字地形“全家桶“(附5m 12.5m 30m 90m DEM下载)

在今年自然资源部发布的《实景三维中国建设技术大纲&#xff08;2021版&#xff09;》中&#xff0c;空间数据部分包括“数字高程模型 &#xff08;DEM&#xff09;、数字表面模型&#xff08;DSM&#xff09;、数字正射影像&#xff08;DOM&#xff09;、 真正射影像&#xff…

ChatGPT火到独立站领域,对FP独立站收款到底有什么影响?

做F牌独立站的商家或多或少都知道&#xff0c;从今年3月份开始&#xff0c;FP独立站的收款就频频出现问题&#xff0c;很多人都跑来问我&#xff0c;第一句话就是&#xff1a;有没有靠谱点的收款渠道&#xff1f; 为什么最近几个月的收款渠道如此稀缺&#xff0c;以前常用的渠道…

防火墙日志记录和监控在网络安全中的重要性

防火墙监视进出网络的流量&#xff0c;并保护部署网络的网络免受恶意流量的侵害。它是一个网络安全系统&#xff0c;根据一些预定义的规则监控传入和传出的流量。它以日志的形式记录有关如何管理流量的信息。日志数据包含流量的源和目标 IP 地址、端口号、协议等。为了有效地保…

代码随想录训练营Day55|● 392.判断子序列 ● 115.不同的子序列

目录 学习目标 学习内容 392.判断子序列 115.不同的子序列 学习目标 392.判断子序列 115.不同的子序列 学习内容 392.判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/is-subsequence/ class Solution:def isSubsequ…

智能电子标签

仓库亮灯拣选标签&#xff0c;让拣货更智能更高效 Warehouse light picking label&#xff0c;Make picking more intelligent and efficient. 控制&#xff1a;通过控制台&#xff0c;对仓库标签进行筛选&#xff0c;需要拣货的标签亮灯Through the console, the warehouse …

谋划高质量增长,拼多多打破电商平台传统路径依赖

经历组织架构调整后&#xff0c;市场格外关注拼多多的最新动向。5月26日&#xff0c;拼多多发布2023年一季度财报&#xff0c;多项财务指标显著超出预期&#xff0c;更激发了市场对拼多多会有哪些战略变动的好奇心。 事实上&#xff0c;自4月初新任联席CEO赵佳臻上任至今&…

信源信道联合编码(Joint Source-channel Coding,JSCC)

目录 为什么需要信源信道联合编码&#xff1f;基于自编码器设计的端到端收发机确定信道模型和未知信道模经典端到端无线通信系统基于深度学习的JSCC 为什么需要信源信道联合编码&#xff1f; 信源编码的目的是去除信源内部冗余信息&#xff0c;提高有效性&#xff1b;信道编码需…

git原理和常用命令

git git介绍git工作流程git的几个核心概念 git常用命令参考资料 git介绍 git-分布式版本控制系统&#xff0c;可以有效、高速的处理从很小到非常大的项目版本管理。 git特点 优点&#xff1a; 适合分布式开发&#xff0c;强调个体&#xff1b; 公共服务器压力和数据量都不会太…

WebService接口测试

WebService的理解 WebService就是Web服务的意思&#xff0c;对应的应用层协议为SOAP&#xff08;相当于HTTP协议&#xff09;&#xff0c;可理解为远程调用技术。 特点&#xff1a; 客户端发送的请求主体内容&#xff08;请求报文&#xff09;的格式为XML格式 接口返回的响…

反射(reflection)基础

反射(reflection) 1. 一个需求引出反射 1.1 请看下面的问题 根据配置文件 re.properties 指定信息,创建Cat对象并调用方法hi 我们用之前的方式处理就是&#xff1a; 先创建一个Cat类&#xff0c;里面创建一个hi()方法; 再创建一个ReflectionQuestion类&#xff0c;然后new …

如何快速开发一个简单实用的MES系统?

01 如何快速开发一个简单实用的MES系统&#xff1f; MES生产管理系统&#xff08;又称制造执行系统&#xff09;是一种集成了计划、生产、质量控制、库存管理和材料申请等生产流程的管理系统&#xff0c;是企业中实现高效生产的重要一环。 根据题主描述“通过产品条形码实现对生…

halcon 3D hom_mat3d_rotate简单测试

半年公司没有订单&#xff0c;公司有想法&#xff0c;所以就让部门领导逼着员工自己提离职&#xff0c;为了让我们自己走&#xff0c;先是公司出各种考核&#xff0c;查我上个月的业绩&#xff0c;给我掉部门&#xff0c;然后就是加工作量&#xff0c;这不&#xff0c;让我一个…

C# 根据条件查询树节点所需的相关数据

默认加载所有的数据&#xff0c;结构长这个样子的。 数据库结构长这个样子的 cParentId上级ID、 cItemCode根节点代码、 cItemTitle根节点名称、 cItemName子节点名称、 cItemValue子节点代码 下面就是业务数据处理的相关逻辑&#xff1a; 核心逻辑如下图&#xff1a; pub…

使用Python实现微信自动回复,操作简单,小白也会使用!秒回女朋友消息 泰裤辣!

文章目录 一、安装itchat库二、登录微信三、实现自动回复四、实现关键词回复五、实现图灵机器人回复总结 Python精品助学大礼包 一、安装itchat库 首先&#xff0c;我们需要安装itchat库&#xff0c;它是一个用于微信个人号的微信Python API&#xff0c;可以用于实现微信自动回…

Java Web实训项目:西蒙购物网

文章目录 一、网站功能需求二、网站设计思路&#xff08;一&#xff09;设计模式&#xff08;二&#xff09;网站前台&#xff08;三&#xff09;网站后台1、用户管理2、类别管理3、商品管理4、订单管理 &#xff08;四&#xff09;购物流程图 三、网站运行效果四、网站实现步骤…

算法设计 || 实验四 回溯算法-八皇后问题(纯手敲保姆级详细讲解+小白适用+头歌解析)

&#xff08;一&#xff09;八皇后问题描述 在一个8x8的棋盘上放置8个皇后&#xff0c;使得每个皇后都不会互相攻击&#xff0c;即任意两个皇后都不能在同一行、同一列或同一条对角线上。 &#xff08;二&#xff09;算法思路 由于八皇后问题的解法数量较多&#xff0c;本文将介…

mysql+Galera+haproxy高可用

文件下载地址环境准备 1.1准备三台服务器 服务器名称 Ip 描述 Node0 xxx.xxx.xxx.xxx Node1 xxx.xxx.xxx.xxx Node2 xxx.xxx.xxx.xxx 1.3 安装依赖包 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config setenforce 0 yum -y install lsof ne…

Axure教程—堆积面积图

本文将教大家如何用AXURE制作堆积面积图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://d4nsae.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87838160 二、功能介绍 简单填写中继器内容即可动态显示值 样式颜色等可…

热榜!阿里出品2023版Java架构师面试指南,涵盖Java所有核心技能

最近很多粉丝朋友私信我说&#xff1a;熬过了去年的寒冬却没熬过现在的内卷&#xff1b;打开Boss直拒一排已读不回&#xff0c;回的基本都是外包&#xff0c;薪资还给的不高&#xff0c;对技术水平要求也远超从前&#xff1b;感觉Java一个初中级岗位有上千人同时竞争&#xff0…

sqlmap的使用详细讲解

一、sqlmap介绍 简介&#xff1a;是一个自动化的sql注入工具&#xff0c;主要功能扫描、发现并利用给定的 url的sql注入漏洞&#xff0c;内置了很多插件 sqlmap支持的数据库&#xff1a; MySQL、oracle、sql-server、DB2.... 注意&#xff1a;sqlmap只用来检测和sq…