JavaScript高级程序设计读书分享之8章——8.1理解对象

news2024/11/18 3:38:12

JavaScript高级程序设计(第4版)读书分享笔记记录

适用于刚入门前端的同志

  •  创建自定义对象的通常方式是创建 Object 的一个新实例,然后再给它添加属性和方法。
let person = new Object()
person.name = 'Tom'
person.age = 18
person.sayName = function(){
    //示 this.name 的值,这个属性会解析为 person.name。
    console.log(this.name) // Tom  
}

以上代码就创建了一个名为person的对象,有两个属性(name,age)和一个方法(sayName)。

  • 使用对象字面量创建对象
let person = {
    name:'Tom',
    age:18,
    sayName(){
        console.log(this.name) //Tom
    }
}

属性的类型

属性分两种:数据属性访问器属性

数据属性

数据属性有 4个特性描述它们的行为:
  •  [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,这个特性都是 true
  •  [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认情况下,这个特性都是 true。
  •  [[Writable]]:表示属性的值是否可以被修改。默认情况下,这个特性都是 true。
  • [[Value]]:包含属性实际的值。这就是前面提到的那个读取和写入属性值的位置。这个特性的默认值为 undefined
要修改属性的默认特性,就必须使用 Object.defineProperty()方法。
这个方法接收 3 个参数:1.要给其添加属性的对象、2.属性的名称和一个描述符对象。最后一个参数,即描述符对象上的属性可以包含:configurable enumerable writable value ,跟相关特性的名称一一对应。
例如:
let person = {}
Object.defineProperty(person,'name',{
    writable:false,
    configurable:false,
    value:'Tom'
})

console.log(person.name) // Tom

//这里修改person对象的name值,是无效的,因为上面writable:false,就说明属性的值不可被修改
person.name = 'Jerry'
console.log(person.name) // Tom

//这里删除person对象的name属性,是删除不了的因为上面configurable:false,就说明该属性不能被delete
delete person.name
console.log(person.name) // Tom

注意

  • 在调用 Object.defineProperty()时,configurableenumerable writable 的值如果不指定,则都默认为 false
  • 此外,一个属性被定义为不可配置之后(false),就不能再变回不能再变回可配置的了再次调用 Object.defineProperty()并修改任何非 writable 属性会导致错误
  • 在不支持 Object.defineProperty() 的浏览器中没有办法修改 [[Configurable]] [[Enumerable]]
 

访问器属性

访问器属性有 4 个特性描述它们的行为
  • [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性。默认情况下,所有直接定义在对象上的属性的这个特性都是 true
  •  [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是 true
  • [[Get]]获取函数,在读取属性时调用。默认值为 undefined
  • [[Set]]:设置函数,在写入属性时调用。默认值为 undefined

访问器属性是不能直接定义的,必须使用 Object.defineProperty()

例子:

// 定义一个对象,包含伪私有成员 year_和公共成员 edition 
let book = { 
 year_: 2017, 
 edition: 1
}

Object.defineProperty(book ,"year",{
    get(){
        return this.year_
    },
    set(newVal){
          if(newVal > 2017){
                this.year_ = newVal
                this.edition += newVal - 2017
            }
    }
})

console.log(book.year) // 2017

book.year = 2018
console.log(book.year) // 2018
console.log(book.edition) // 2

定义多个属性

ECMAScript 提供 Object.defineProperties()方法。这个方法可以通过多个描述符一次性定义多个属性。
它接收两个参数:1.要为之添加或修改属性的对象,2.另一个描述符对象,其属性与要添加或修改的属性一一对应

let book = {}; 
Object.defineProperties(book, { 
    year_: { 
        value: 2017 ,
        // writable:true
    }, 
    edition: { 
        value: 1 ,
        // writable:true
    }, 
    year: { 
        get(){ 
            return this.year_; 
        },
        set(newValue){
            console.log("1112222222222",newValue)
            if (newValue > 2017) { 
                this.year_ = newValue; 
                console.log("1112222222222" ,this.year_)
                this.edition += newValue - 2017; 
            }
        }
    }
})
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1


//此时这里修改了year 的值 但是打印没变
book.year = 2018

console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1

注意:

唯一的区别是所有属性都是同时定义的,并且数据属性的configurable、 enumerable writable 特性值都是 false。!!!
所以上面修改了year还是没变,就要把writable改为true

let book = {}; 
Object.defineProperties(book, { 
    year_: { 
        value: 2017 ,
        writable:true
    }, 
    edition: { 
        value: 1 ,
        writable:true
    }, 
    year: { 
        get(){ 
            return this.year_; 
        },
        set(newValue){
            console.log("1112222222222",newValue)
            if (newValue > 2017) { 
                this.year_ = newValue; 
                console.log("1112222222222" ,this.year_)
                this.edition += newValue - 2017; 
            }
        }
    }
})
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1

book.year = 2018

console.log(book.year_) // 2018
console.log(book.year) // 2018
console.log(book.edition) // 1

读取属性的特性

使用 Object.getOwnPropertyDescriptor()方法可以取得指定属性的属性描述符。这个方法接收两个参数:属性所在的对象和要取得其描述符的属性名。返回值是一个对象

接上面的book例子:

let descriptor = Object.getOwnPropertyDescriptor(book, "year_"); 
console.log(descriptor.value); // 2017 
console.log(descriptor.configurable); // false 
console.log(typeof descriptor.get); // "undefined" 

let descriptor = Object.getOwnPropertyDescriptor(book, "year"); 
console.log(descriptor.value); // undefined 
console.log(descriptor.enumerable); // false 
console.log(typeof descriptor.get); // "function"

ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors()静态方法,返回值是一个对象

接上面的book例子:

let descript =  Object.getOwnPropertyDescriptors(book)
console.log(descript )

打印值:

合并对象

ECMAScript 6 专门为合并对象提供了 Object.assign() 方法
  • 这个方法接收一个目标对象和一个或多个源对象作为参数。
  • 注意:Object.assign()的属性拷贝是浅拷贝
  • 同名属性替换,如果多个源对象都有相同的属性,则使用最后一个复制的值。
示例:
let dest ,src, result;

//一个源对象
dest = {}
src = {id:'src'}

result = Object.assign(dest,src)
console.log(result ) // {id:'src'}

//多个源对象
dest = {}
result = Object.assign(dest, { a: 'foo' }, { b: 'bar' }); 
console.log(result); // { a: foo, b: bar }


// 浅复制体现
dest = {} 
src = { a:{b:1}}

result  = Object.assign(dest ,src)
console.log(result) // { a:{b:2}} 因为是浅复制,值指向同一位置
console.log(result.a.b) // 1 
src.a.b = 2
console.log(result.a.b) // 2


//覆盖属性
dest = {id:'dest'}
result  = Object.assign(dest ,{id:'src',a:1},{id:'test',b:2})
console.log(result  ) // {id:'test',a:1,b:2}



对象标识及相等判定

ECMAScript 6 规范新增了 Object.is()
  • 这个方法与===很像,用来比较两个值是否严格相等。
  • 这个方法必须接收两个参数
Object.is("q","q");      // true
Object.is(1,1);          // true
Object.is([1],[1]);      // false
Object.is({q:1},{q:1});  // false

与 === 的区别

//一是+0不等于-0
console.log( Object.is(+0,-0) );  //false
console.log( +0 === -0 )   //true
//二是NaN等于本身
console.log ( Object.is(NaN,NaN) ); //true
console.log (NaN === NaN)  //false

增强的对象语法

ECMAScript 6 为定义和操作对象新增了很多极其有用的语法糖特性

属性简写

ES6允许对象的属性直接写变量,这时候属性名是变量名,属性值是变量值。

const age = 12;
const name = "Amy";
const person = {age, name};
console.log(person) //{age: 12, name: "Amy"}
//等同于
const person = {age: age, name: name}

可计算属性

有了可计算属性,就可以在对象字面量中完成动态属性赋值
const nameKey = 'name'; 
const ageKey = 'age'; 
const jobKey = 'job'; 
let person = { 
 [nameKey]: 'Matt', 
 [ageKey]: 27, 
 [jobKey]: 'Software engineer' 
}; 
console.log(person); // { name: 'Matt', age: 27, job: 'Software engineer' }

简写方法名

const person = {
  sayHi(){
    console.log("Hi");
  }
}
person.sayHi();  //"Hi"


//等同于
const person = {
  sayHi:function(){
    console.log("Hi");
  }
}
person.sayHi();//"Hi"

对象解构

ECMAScript 6 新增了对象解构语法,可以在一条语句中使用嵌套数据实现一个或多个赋值操作
// 使用对象解构
let person = { 
 name: 'Matt', 
 age: 27 
}; 
let { name: personName, age: personAge } = person; 
console.log(personName); // Matt 
console.log(personAge); // 27
让变量直接使用属性的名称,那么可以使用简写语法。
let person = { 
 name: 'Matt', 
 age: 27 
}; 
let { name, age } = person; 
console.log(name); // Matt 
console.log(age); // 27
        解构并不要求变量必须在解构表达式中声明。不过,如果是给事先声明的变量赋值,则赋值表达式必须包含在一对括号中:
let personName, personAge; 
let person = { 
 name: 'Matt', 
 age: 27 
}; 
({name: personName, age: personAge} = person); 
console.log(personName, personAge); // Matt, 27

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

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

相关文章

MySQL运维篇之主从复制

02、主从复制 2.1、概述 主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进行复制&…

Vue+ElementUI+SpringBoot项目配合分页插件快速实现分页(简单暴力)

首先需要在项目中引入Element-UI的组件库,使用以下命令,不会引入的请自行百度。 npm i element-ui -S Element官网地址:https://element.eleme.cn/#/zh-CN/component/changelog 去Element-UI官网组件库找到合适的分页插件,并把他引…

HashMap的7种遍历方式

目录1.JDK 8 之前的遍历1.1 EntrySet 遍历1.2 KeySet 遍历1.3 EntrySet 迭代器遍历1.4 KeySet 迭代器遍历2.JDK 8 之后的遍历2.1 Lambda 遍历2.2 Stream 单线程遍历2.3 Stream 多线程遍历3.总结1.JDK 8 之前的遍历 1.1 EntrySet 遍历 public static void main(String[] args) …

高压功率放大器在径向驻波型超声波电机研究中的应用

实验名称:大力矩径向驻波型超声波电机有限元分析与实验研究研究方向:超声电机测试目的:提出了一种大力矩径向驻波型超声波电机,在实现电机大力矩输出的同时保持结构紧凑的特点。首先设计并分析了电机的结构和工作原理,…

Biomod2 (上):物种分布模型预备知识总结

Biomod11.栅格数据处理1.1 读取一个栅格图片1.2 计算数据间的相关系数1.3 生成多波段的栅格图像1.4 修改变量名称1.4.1 计算多个变量之间的相关性2. 矢量数据处理2.1 提取矢量数据2.2 数据掩膜2.2 栅格计算2.3 拓展插件的使用3. 图表绘制3.1 遥感影像绘制3.2 柱状图分析图绘制3…

C语言循环控制语句Break,goto,continue语句讲解

循环控制语句改变你代码的执行顺序。通过它你可以实现代码的跳转。 C 语言中 break 语句有以下两种用法: 当 break 语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。 它可用于终止 switch 语句中的一个 …

【日志框架-笔记】深入浅出 Log4j,理论-源码-配置

log4j一、log4j 的概述及其入门程序入门程序二、日志输出的需要及PatternLayout类源码分析日志输出的需要PatternLayout类的源码分析三、Log4j 占位符的具体含义四、Log4j 配置文件实操如何对配置文件进行解析的?(LogManager的静态代码块)实操五、自定义…

ClickHouse的架构与基本概念

一、ClickHouse的定义 ClickHouse是一个完全的列式分布式数据库管理系统(DBMS),允许在运行时创建表和数据库,加载数据和运行查询,而无需重新配置和重新启动服务器,支持线性扩展,简单方便,高可靠性&#xf…

spring spring-boot @valid @NotNull @NotEmpty 基本校验使用以及 全局异常优化集成

valid NotNull NotEmpty 一套标准的基础校验&#xff0c;可以将校验注解和附带错误信息添加到请求入参上即可完成校验&#xff0c;可以去除简单的校验代码&#xff0c;节省一定的时间和代码量 Maven 依赖 spring-boot <dependency><groupId>org.springframewor…

【已解决】VM中安装的Ubuntu窗口太小、无法和Windows复制粘贴

按理说窗口都是铺满VM的&#xff0c;可是有时候安装Ubuntu之后发现小太了&#xff0c;就800*600&#xff08;4:3&#xff09; 1 窗口太小方法一 在桌面右键&#xff0c;打开display settings 调整resolution&#xff0c;选择你需要的即可&#xff0c;但是这样的调整不是很完…

结构体占用内存大小如何确定?-->结构体字节对齐 | C语言

目录 一、什么是结构体 二、为什么需要结构体 三、结构体的字节对齐 3.1、示例1 3.2、示例2 3.3、示例3 3.4、示例4 3.5、示例5 四、结构体字节对齐总结 一、什么是结构体 结构体是将不同类型的数据按照一定的功能需 求进行整体封装&#xff0c;封装的数据类型与大小均…

日期:Date,SimpleDateFormat常见API以及包装类

一.Date类 package com.gch.d1_date;import java.util.Date;/**目标:学会使用Date类处理时间,获取时间的信息*/ public class DateDemo1 {public static void main(String[] args) {// 1.创建一个Date类的对象:代表系统此刻日期时间对象Date d new Date();System.out.println(…

什么是pod类型

很久很久以前&#xff0c;C 语言统一了江湖。几乎所有的系统底层都是用 C 写的&#xff0c;当时定义的基本数据类型有 int、char、float 等整数类型、浮点类型、枚举、void、指针、数组、结构等等。然后只要碰到一串01010110010 之类的数据&#xff0c;编译器都可以正确的把它解…

做软件测试,如何才能实现月入20K?

听我的&#xff0c;测试想要月入20k。 首先你要去大厂&#xff0c;不在大厂起码也得在一线城市&#xff0c;北上广深。 二线城市的话成都、杭州最好。 不然的话想都不要想。 像我之前整理过成都的公司&#xff0c;除了字节跳动、蚂蚁金服、滴滴、美团、京东、平安、字节跳动…

超简单的计数排序!!

假设给定混乱数据为&#xff1a;3&#xff0c;0&#xff0c;1&#xff0c;3&#xff0c;6&#xff0c;5&#xff0c;4&#xff0c;2&#xff0c;1&#xff0c;9。 下面我们将通过使用计数排序的思想来完成对上面数据的排序。(先不谈负数) 计数排序 该排序的思路和它的名字一样…

Java——图像渲染

题目链接 leetcode在线oj题——图像渲染 题目描述 有一幅以 m x n 的二维整数数组表示的图画 image &#xff0c;其中 image[i][j] 表示该图画的像素值大小。 你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。 为了完成…

互联网医院系统软件开发|互联网医院管理系统开发的好处

互联网医院一直是现在的热门行业&#xff0c;很多的医院已经开发了互联网医院&#xff0c;并且已经在良好的运行中&#xff0c;而有一些医院和企业正在开发中&#xff0c;或者打算开发互联网医院系统&#xff0c;其实这些企业和医院还是很有远见的&#xff0c;因为他们知道并了…

Swift 第三方 播放器AliyunPlayer(阿里云播放器)(源码)

一直觉得自己写的不是技术&#xff0c;而是情怀&#xff0c;一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的&#xff0c;希望我的这条路能让你们少走弯路&#xff0c;希望我能帮你们抹去知识的蒙尘&#xff0c;希望我能帮你们理清知识的脉络&#xff0…

卡尔曼滤波——一种基于滤波的时序状态估计方法

文章目录1. Kalman滤波及其应用2. Kalman原理公式推导&#xff1a;Step 1&#xff1a;模型建立Step 2&#xff1a;开始Kalman滤波Step 3&#xff1a;迭代滤波本文是对 How a Kalman filter works, in pictures一文学习笔记&#xff0c;主要是提炼核心知识&#xff0c;方便作者快…

已解决pip install wxPython模块安装失败

已解决&#xff08;pip install wxPython安装失败&#xff09;error: legacy-instal1-failure Encountered error while trying to install package.wxPython note: This is an issue with the package mentioned above&#xff0c;not pip. hint : See above for output from …