红宝书系列之 对象(一)
目录
1. 定义
1.1 创建对象
2.属性的类型
2.1 数据属性
2.2 修改默认属性
2.3 访问器属性
3.对象的操作
3.1 定义多个属性 Object.defineProperties( )
3.2 读取属性的特性
Object.getOwnPropertyDescriptor( )
Object.getOwnPropertyDescriptors( )
3.3 合并对象 Object.assign( )
4.增强的对象语法
4.1 属性值简写
4.2 可计算属性
5. 对象解构
1. 定义
ECMA-262 将对象定义为一组属性的无序集合,可以把对象想象成一张散列表。对象的每个属性或方法都由一个名称来标识,这个名称映射到一个值。(也就是键值对)
1.1 创建对象
- 通常方法
先创建一个 Object 实例,然后给它添加属性和方法(有点麻烦)
let person = new Object();
person.name = 'mike';
person.age = 18;
person.sayName = function() {console.log(this.name);
};
- 对象字面量方法
let person = {name: 'mike',age: 18,sayName() {console.log(this.name);}// 也可以写成这样// sayName: function() {// console.log(this.name);// }
};
2.属性的类型
属性包括两种
- 数据属性
- 访问器属性
特性的定义:ECMA-262 使用一些内部特性来描述属性的特征。这些特性是由为 JavaScript 实现引擎的规范定义 的。因此,开发者不能在 JavaScript 中直接访问这些特性。为了将某个特性标识为内部特性,规范会用两个中括号把特性的名称括起来,比如 [[ Enumerable ]] 。
2.1 数据属性
数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有4个特性描述它们的行为。
- [[ configurable ]] : 表示属性是否可以通过 delete 删除并重新定义,是否可以修改他的特性。以及是否可以把它变成访问器属性。默认是 true
- [[ Enumerable]] : 表示属性是否可以通过 for-in 循环返回。默认是 true
- [[ Writable ]] : 表示属性是否可以被修改。默认是 true
- [[ Value ]] : 表示属性的实际值,默认未赋值的情况下是 undefined
例如:
let person = {name: 'mike'
}
这里创建了一个名为 name 的属性,且赋值为 mike ,那么前面三个特性 [[ configurable ]] [[ Enumerable]] [[ Writable ]] 都会是默认值 true , [[ Value ]] 为 ' mike '
2.2 修改默认属性
使用 Object.defineProperty() 方法,接收三个参数:属性对象、属性名称、描述符对象
let person = {name: 'mike'
}
Object.defineProperty(person,"name", {writable: false
})
person.name = 'alice'
console.log(person.name); // mike
上面的例子,在非严格模式下尝试重新赋值会被忽略,在严格模式下会报错
Tips:
- 如果把 [[ configurable ]] 设置为 false,该属性变成不可配置后,就不能再变回可配置了。再次调用 Object.defineProperty() 修改除 [[ writable ]] 之外的所有属性都会报错
- 在调用 Object.defineProperty() 时如果没有给 configurable enumberable writable 指定值,就会默认是 false (例如 3.1 的例子)
- 多数情况下,可能不需要 Object.defineProperty() 提供这些强大的设置,但要知道这些概念
2.3 访问器属性
访问器属性不包含数值。它们包含一个获取函数(getter)和一个设置函数(setter),不过这两个函数不是必需的。在读取时会调用 getter ,在写入时调用 setter
访问器属性不是直接定义的,必须通过 Object.defineProperty()
访问器属性有4个特性
- [[ configurable ]] : 表示属性是否可以通过 delete 删除并重新定义,是否可以修改他的特性。以及是否可以把它变成访问器属性。默认是 true
- [[ Enumerable]] : 表示属性是否可以通过 for-in 循环返回。默认是 true
- [[ Get ]] : 获取函数,在读取属性时使用,默认为 undefined
- [[ Set ]] : 设置函数,在写入属性时使用,默认为 undefined
例如:
let book = {year_: 2023, // 数据属性,通常情况下下划线表示该属性并不希望在对象方法的外部使用edition: 1 // 数据属性
};// 定义访问器属性
Object.defineProperty(book,"year", {get() {return this.year_;},set(value) {if(value > 2023) {this.year_ = value;this.edition += value - 2023;}}
});
// 使用访问器属性
book.year = 2025;
console.log(book.edition); // 3
在上面的例子中,修改 year 属性会导致 year_ 和 edition 都会进行更新。这个就是访问器属性的典型使用场景,设置一个属性会导致其他属性发生一些变化。
Tips:
- 虽然获取函数和设置函数并不是一定需要定义的。但是如果你只定义了获取函数,也就意味着该属性是只读的,当你想要尝试修改属性时,非严格模式会忽略,严格模式会报错。反之也是如此
3.对象的操作
3.1 定义多个属性 Object.defineProperties( )
Object.defineProperties( ) 接收两个参数,第一个是添加或修改属性的对象,第二个是描述符对象
let book = {};
Object.defineProperties(book,{year_: { // 数据属性value: 2023}, edition: { // 数据属性value: 1 },year: { // 访问器属性get() {return this.year_;},set(value) {if(value > 2023) {this.year_ = value;this.edition += value - 2023;}}}
})
这个例子中定义的 book 对象跟 2.3 例子中的 book 对象是一样的。区别就是数据属性 year_ 和edition 由于没有指定 configurable enumerable 和 writable 特性值,所以全都设置为 false
3.2 读取属性的特性
Object.getOwnPropertyDescriptor( )
Object.getOwnPropertyDescriptor( ) 接收两个参数,第一个是要访问的对象名,另一个是属性名(要以字符串的形式)。返回值是一个对象,返回数据属性和访问器属性的四个特性
let book = {};
Object.defineProperties(book,{year_: { // 数据属性value: 2023}, edition: { // 数据属性value: 1 },year: {get() {return this.year_;},set(value) {if(value > 2023) {this.year_ = value;this.edition += value - 2023;}}}
})let descriptor = Object.getOwnPropertyDescriptor(book,"year_");
console.log(descriptor);
// {
// value: 2023,
// writable: false,
// enumerable: false,
// configurable: false
// }let descriptor1 = Object.getOwnPropertyDescriptor(book,"year");
console.log(descriptor1);
// {
// get: [Function: get],
// set: [Function: set],
// enumerable: false,
// configurable: false
// }
Object.getOwnPropertyDescriptors( )
该函数接收一个参数为要访问的对象,返回值是一个对象。该函数实际上会在对象的每个自有属性上调用 Object.getOwnPropertyDescriptor( ) ,合并在一个新对象后返回。
let book = {};
Object.defineProperties(book, {year_: { // 数据属性value: 2023},edition: { // 数据属性value: 1},year: {get() {return this.year_;},set(value) {if (value > 2023) {this.year_ = value;this.edition += value - 2023;}}}
})let descriptors = Object.getOwnPropertyDescriptors(book);
console.log(descriptors);
// {
// year_: {
// value: 2023,
// writable: false,
// enumerable: false,
// configurable: false
// },
// edition: {
// value: 1,
// writable: false,
// enumerable: false,
// configurable: false
// },
// year: {
// get: [Function: get],
// set: [Function: set],
// enumerable: false,
// configurable: false
// }
// }
3.3 合并对象 Object.assign( )
- Object.assign( ) 这个方法接收一个目标对象和一个或多个源对象作为参数。返回值是修改后的目标对象。
- 将源对象中可枚举和自有的属性复制到目标对象中。(使用源对象的 [[ Get ]] 特性方法获取值,使用目标对象的 [[ Set ]] 特性方法设置属性值
简单复制
let dest = {a: 'aaa'
}
let src = {b: 'bbb'
}let k = Object.assign(dest,src, { c: 'ccc'} );console.log(dest);
// { a: 'aaa', b: 'bbb', c: 'ccc' }console.log(k);
// { a: 'aaa', b: 'bbb', c: 'ccc' }
获取函数和设置函数
let dest = {set (val) {console.log(`This is ${val}`);}
}let src = {get () {console.log('src getter');return 'foo';}
}Object.assign(dest,src);dest.get(); // src getter
覆盖属性,重复的属性会进行覆盖
let dest = {a: 'aaa',b: 'bbb'
}let src = {a: 'zzz'
}Object.assign(dest, src, { a: 'kkk' });console.log(dest);
// { a: 'kkk', b: 'bbb' }
4.增强的对象语法
4.1 属性值简写
当属性名和变量名相等时,可以直接简写属性名即可。当简写时,如果没有找到同名变量,则会抛出 ReferenceError
let name = 'mike';
function sayName() {console.log(this.name);
}let dest = {name, // 等价于 name: nameage: 18,sayName // 函数也适用
}console.log(dest);
// { name: 'mike', age: 18, sayName: [Function: sayName] }dest.sayName(); // mike
4.2 可计算属性
- 如果想要用一个变量来定义属性名的话,要使用中括号语法,不然会直接识别成字符串。
Tips
- 变量中途发生改变,要重新定义 person 才会在 person 上生效
let key = 'job';let person = {[key]: 'good'
}console.log(person.job); // goodkey = 'class';console.log(person.class); // undefined 要重新定义对象才有用
console.log(person.job); // good// 重新定义对象 person 变量改动后的值才生效
person = {[key]: 'bad'
}console.log(person.class); // bad
console.log(person.job); // undefined
- 函数返回值也可以充当属性名
let nameKey = 'name';function getKey(count) {return `${nameKey}_${count}`;
}let person = {[getKey(1)] : 'aaa'
}console.log(person);
// { name_1: 'aaa' }
5. 对象解构
ES6 新增了对象结构语法,可以在一条语句中使用嵌套数据实现一个或多个赋值操作。
- 不解构时
let person = {name: 'mike',age: 18
}
let personName = person.name;
let personAge = person.age;console.log(personName); // mike
console.log(personAge); // 18
- 解构时,简单轻松
let person = {name: 'mike',age: 18
}
let { name: personName, age: personAge } = person;console.log(personName); // mike
console.log(personAge); // 18
- 如果属性名和要赋值的变量名相等,甚至可以简写
let person = {name: 'mike',age: 18
}
let { name, age, job } = person;console.log(name); // mike
console.log(age); // 18
console.log(job); // undefined 当属性不存在时 undefined
Tips:
- 解构时会自动帮你生成变量,如果要给事先声明过的变量赋值,则表达式必须包含在一对括号中。
let personName,personAge;let person = {name: 'mike',age: 18
};({ name: personName, age: personAge } = person);console.log(personName); // mike
console.log(personAge); // 18
终于写完了,不过未完待续......
红宝书系列之 对象(一)相关推荐
- 红宝书系列之 对象(二)
目录 一.创建对象(接口方法) 1.1 工厂模式 1.2 构造函数模式 二.构造函数 2.1 构造函数也是函数 2.2 构造函数的问题 优化 一.创建对象(接口方法) 虽然使用 Object 构造函数 ...
- 红宝书系列之 var let const 的区别
目录 声明风格及最佳实践 var 关键字 1. var 使用 2. var 声明作用域 3. var 声明提升 let 声明 1. let 作用域 2. 暂时性死区 3. 全局声明(网易前端笔试题) ...
- 游戏开发计算机图形学杂项知识系列:OpenGL红宝书中第一个渲染程序Triangles常见问题归总
游戏开发计算机图形学杂项知识系列:OpenGL红宝书中第一个渲染程序Triangles常见问题归总 声明:未经作者允许,严禁商用,转载请标明出处和来源,谢谢 转载自:https://www.cnblo ...
- 红宝书初步研读随手笔记
红宝书初步研读系列–第一二三章 红宝书第一遍研读,知识点整理–随手笔记 第一章 什么是JavaScriptS 1.1. JavaScript包括: ECMAScript (核心)DOM(文档对象模型) ...
- 《JavaScript高级程序设计(第四版)》红宝书学习笔记(2)(第四章:变量、作用域与内存)
个人对第四版红宝书的学习笔记.不适合小白阅读.这是part2.持续更新,其他章节笔记看我主页. (记 * 的表示是ES6新增的知识点,记 ` 表示包含新知识点) 第四章:变量.作用域与内存 4.1 原 ...
- 《JavaScript高级程序设计(第四版)》红宝书学习笔记(1)
个人对第四版红宝书的学习笔记.不适合小白阅读.这是part1,包含原书第二章(HTML中的Javascript)和第三章(语言基础).持续更新,其他章节笔记看我主页. (记 * 的表示是ES6新增的知 ...
- 《JavaScript高级程序设计》红宝书第二遍阅读(动手实践)
<JavaScript高级程序设计>红宝书第二遍阅读(动手实践) 第1章--什么是JavaScript 第2章--HTML中的JavaScript 第3章--语言基础 第4章--变量.作用 ...
- 《JavaScript高级程序设计》红宝书第一遍阅读(了解概念)
<JavaScript高级程序设计>红宝书第一遍阅读(了解概念) 第1章--什么是JavaScript 第2章--HTML中的JavaScript 第3章--语言基础 第4章--变量.作用 ...
- OpenGL红宝书的部分学习记录
我看的OpenGL红宝书为: <OpenGL编程指南>-- 原书第9版 OpenGL Programming Guide – The Official Guide to Learning ...
最新文章
- ffmpeg 怎么处理udp音频_视音频数据处理入门:UDP-RTP协议解析
- The Digits String
- koa中间件机制详解
- 使用Git版本控制查看文件的更改历史记录
- c++ 二维数组_C|数形结合理解数组指针、指针数组、一级指针来遍历二维数组
- 网络安全系统性学习路线「全文字详细介绍」
- 2020人脸识别报告:上万家企业入局,八大技术六个趋势一文看尽
- 浪潮服务器一键还原系统,一键恢复 怎样做备份
- ThreadX视频教程第2期:通俗易懂的介绍Cortex-M内核的OS特性,双堆栈,非特权级,PendSV,SVC,Systick等,争取人人都可以掌握
- Map集合简单应用的例子(世界杯)
- 百度搜索开放平台,百度搜索api
- 计算机技术学硕国家线,关于工科国家线专硕学硕
- Windows 10 - 安装 Mysql - zip压缩包详细安装教程
- 红楼梦评论--王国维
- 【信管1.6】计算机网络基础(四)网络规划与数据软件
- 计蒜客信息学入门赛 #16--B
- 《疯狂Java讲义》(第5版) 作者李刚(待重新排版)
- python秒数转化为时间用户jianpang_Python写了个域名注册查询脚本,支持自定义数字,字母,拼音组合以及域名长度....
- Windows下安装C环境
- 利用ArcGIS结合DEM提取小流域单元