本章节的主要内容是: ES6 对象扩展
一: 对象扩展
1. 属性的简洁表示方法
2. 属性表达式
3. 扩展运算符
4. Object 新增方法
/**
1.1 普通属性
*/
// ES5 对象写法
{
// 示例一
let str1 = '字符'
let num1 = 11111
let objES5 = {
str1: str1,
num1: num1
}
console.log('ES5 对象写法: ', objES5); // ES5 对象写法: {str1: '字符', num1: 11111}
}
// ES6 写法
{
// 示例一
// 对比 ES5 对象写法中的 '示例一', 它们的结果并没有什么不同, 只是写法上更加简洁 。
let str1 = '字符'
let num1 = 11111
let objES6 = {
str1,
num1
}
console.log('ES6 对象写法: ', objES6); // ES6 对象写法: {str1: '字符', num1: 11111}
}
/**
1.2 对象中的方法
1. ES6 中的写法比 ES5 中的写法简洁的多: 我们可以将 " : 与 function " 关键字省去 。
*/
// ES5 写法
{
let es5_method = {
hello: function() {
console.log('ES5 中方法的写法 -- 使用方法对比是否不同 (ES5)');
}
}
es5_method.hello() // ES5 中方法的写法 -- 使用方法对比是否不同 (ES5)
}
// ES6 写法
{
let es6_method = {
hello() {
console.log('ES6 中方法的写法 -- 使用方法对比是否不同 (ES6) ');
}
}
es6_method.hello() // ES6 中方法的写法 -- 使用方法对比是否不同 (ES6)
}
/**
1.3 函数返回值
*/
{
function fun1() {
let x = 1
let y = 2
// ES6 写法
return {x, y}
// // ES5 实现方法
// return {
// x: x,
// y: y
// }
}
console.log(fun1()); // {x: 1, y: 2}
}
/**
1.4 CommonJS 模块输出变量
*/
// 假设下面的代码是一个 .JS 文件中的内容, 使用 CommonJS 模块化方法输出内容
{
var ms = {a: 1}
function fn1() {
return 1 + 2
}
function fn2() {
return 2+3
}
function fn3() {
ms = {}
}
// moudle.exports = {
// ms,
// fn1,
// fn2,
// fn3
// }
}
/**
2. 属性名表达式: []
1. 在 ES5 中, 对象的 key 值是固定的; 在 ES6 中 key 值是可以用表达式也可以使用变量来作为 key 使用的 。
2. 注意细节知识点:
1. '属性名表达式' 与 '简介表示法' 不能同时使用, 否则会报错 。
*/
// ES5 写法
{
let a = 'abc'
let es5_obj = {
a: 'ddddd'
}
console.log(es5_obj); // {a: 'ddddd'}
}
// ES6 写法
{
let a = 'abc'
let es6_obj = {
// 字面量定义对象的属性名
[a]: 'ddddd',
// 表达式作为对象的属性名
['k' + 'ey' + 'Val']: 'kkkkk',
// 表达式用于定于方法名
['f' + 'un' + '1']() {
return '表达式用于定于方法名'
}
}
console.log(es6_obj); // {abc: 'ddddd', keyVal: 'kkkkk', fun1: ƒ}
}
/**
3. 扩展运算符 ...
1. 结构赋值:
1. 对象的解构赋值用于从一个对象取值, 相当于将所有可遍历的、但尚未被读取的属性分配到指定的对象上 。
2. 注意:
1. 对象的解构赋值要求等号右边是一个对象; 如果等号右边是 undefined 或 null 会报错, 因为它们不能转换为对象 。
2. 解构赋值的复制是浅复制 。
1. 注意:
1. 为了正常运行当前语法, 我们需要安装: cnpm install babel-preset-stage-2 --save; 在 .babelrc 文件中 presets 选项中, 添加 "stage-2" 。
2. 通常安装到 stage-2 就够用了, 如果还不行, 再安装 stage-1 或者 stage-0 <越小越新> 。
1.
*/
{
// 解构赋值:
let {a, b, ...c} = {a: '1', b: '2', c: '3', d: '4'}
console.log('对象的扩展运算符: ', c); // 对象的扩展运算符: {c: '3', d: '4'}
// undefined 或 null 会报错
// let {a1, b1, ...c1} = undefined // 报错
// let {a2, b2, ...c2} = null // 报错
// 解构赋值的复制是浅复制
}
/**
4.1 Object.is()
1. 判断两个值是否相等
*/
{
console.log('判断两个字符串是否相等: ', 'ES6: ', Object.is('abc', 'abc'), 'ES5: ', 'abc' === 'abc'); // 判断两个字符串是否相等: ES: true ES5: true
/**
* 1. 数组是引用类型, 虽然都是空数组, 在值上都是空, 但是这两个数组引用的是两个不同的地址, 所以在严格意义上来讲它们是不相等的 。
* 2. Object.is() 的功能与 ===(严格相等运算符) 的功能没有区别 。
*/
console.log('判断两个数组是否相等<引用类型>', 'ES6: ', Object.is([], []), 'ES5: ', [] === []); // 判断两个数组是否相等<引用类型> ES6: false ES5: false
}
/**
4.2 Object.assign()
1. 拷贝功能
2. 细节知识点:
1. Object.assign 实现的是浅拷贝 。
1. 浅拷贝只拷贝引用地址, 而不是将值真正的拷贝过去 。
2. 这个方法拷贝的只是自身的属性, 如果这个对象还有继承属性, 它是不会拷贝继承属性的 。
3. 同时也不能拷贝不可枚举的属性 。
*/
{
let obj1 = {a: 'a'}
let obj2 = {b: 'b'}
let objAss = Object.assign(obj1, obj2)
console.log('拷贝功能: ', objAss, obj1, obj2); // 拷贝功能: {a: 'a', b: 'b'} {a: 'a', b: 'b'} {b: 'b'}
// 修改
obj2.b = '111111111'
console.log('修改: 单层深拷贝 ----- : ', objAss, obj1, obj2) // 修改 ----- : {a: 'a', b: 'b'} {a: 'a', b: 'b'} {b: '111111111'}
// 源对象属性的值为对象
let a1 = {a: '111'}
let a2 = {b: '222', c: {d: '3333'}}
let asA = Object.assign({}, a1, a2)
console.log(asA, a1, a2); // {a: '111', b: '222', c: {d: '3333'}} {a: '111'} {b: '222', c: {d: '3333'}}
a2.c.d = '修改属性值为对象的结果---3333'
console.log(asA, a1, a2); // {a: '111', b: '222', c: {d: '修改属性值为对象的结果---3333'}} {a: '111'} {b: '222', c: {d: '修改属性值为对象的结果---3333'}}
// 注意: 如果目标对象与源对象有同名属性, 或者多个源对象有同名属性, 则后面的属性会覆盖前面的属性
let o1 = {a:1, b:2}
let o2 = {b: 3, c: 4}
let o3 = {c: 5}
Object.assign(o1, o2, o3)
console.log('属性覆盖 -- o1: ', o1); // 属性覆盖 -- o1: {a: 1, b: 3, c: 5}
// 如果只有一个参数, Object.assign 会直接返回该参数
let b1 = {a: 2}
console.log('只有一个参数 -- b1: ', Object.assign(b1) === b1); // 只有一个参数 -- b1: true
}
// 为对象添加属性:
{
class Point {
constructor(x, y) {
// 通过 Object.assign 方法将 x 、 y 属性添加到 Point 类的对象实例中 。
Object.assign(this, {x, y})
}
}
// let point = new Point
// console.log(point.x);
}
// 为对象添加方法:
{
class SomeClass {}
Object.assign(SomeClass.prototype, {
// 直接将两个函数放在大括号中, 使用 Object.assign 方法添加到 SomeClass.prototype 中
someMethod(arg1, arg2) {
},
anotherMethod() {
}
})
}
/**
5. Object.getOwnPropertyDescriptor()
1. 可以获取属性的描述对象 。
1. 属性的可枚举型:
*/
{
let obj1 = {foo: 123}
console.log(Object.getOwnPropertyDescriptor(obj1, 'foo'));
// 打印结果:
// {
// value: 123,
// writable: true, // 对象属性是否可修改; flase 为不可修改, 默认值为 true 。
// enumerable: true, // 可枚举型; 如果为 false, 某些操作可以忽略当前属性 。
// configurable: true // 能否使用 delete / update, 能否需改属性特性 、 或能否修改访问器属性; false 为不可重新定义, 默认值为 true 。
// }
/**
* 1. Object.assign 会忽略 enumerable 为 false 的属性, 只赋值对象的可枚举属性 。
* 2. 注意:
* 1. ES6 规定, class 的原型的方法都是不可枚举的 。
*/
}
/**
6. 属性的遍历
1. for...in : 循环遍历对象自身和继承的可枚举属性(不含 Symbol 属性) 。
2. Object.keys(obj) : 返回数组; 对象自身<不包含继承>和可枚举属性(不含 Symbol 属性) 。
3. Object.getOwnPropertyNames(obj) : 返回数组; 包含自身的所有属性 <不含 Symbol 属性, 但是包含不可枚举的属性> 。
4. Object.getOwnPropertySymbols(obj) : 返回一个数组; 包含自身所有的 Symbol 属性 。
5. Reflect.ownKeys(obj) : 返回一个数组; 包含对象自身的所有属性, 不管属性名是 Symbol 还是字符串, 也不管是否可枚举 。
细节知识点:
1. Object.keys() 与 Reflect.ownKeys() 的区别:
1. Object.keys() 返回属性 key, 但不包括不可枚举的属性 。
2. Reflect.ownKeys() 返回所有属性 key 。
*/
{
let obj = {
a: 1,
b: {b1: 2},
c: [3, 4],
d: {
d1: 5,
d2: {d3: 6},
d4: {d5: [7,8]}
},
[Symbol()]: 123
}
// for...in
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
console.log('属性的遍历--for...in: ', key);
// // 打印结果:
// 属性的遍历--for...in: a
// 属性的遍历--for...in: b
// 属性的遍历--for...in: c
// 属性的遍历--for...in: d
}
}
// Object.keys(obj)
console.log('属性的遍历--Object.keys: ', Object.keys(obj)); // 属性的遍历--Object.keys: ['a', 'b', 'c', 'd']
// Object.getOwnPropertyNames
console.log('属性的遍历--Object.getOwnPropertyNames: ', Object.getOwnPropertyNames(obj));
// 打印结果:
// 属性的遍历--Object.getOwnPropertyNames: ['a', 'b', 'c', 'd']
// Object.getOwnPropertySymbols
console.log('属性的遍历--Object.getOwnPropertySymbols: ', Object.getOwnPropertySymbols(obj));
// 打印结果:
// 属性的遍历--Object.getOwnPropertySymbols: [Symbol()]
// Object.ownKeys
console.log('属性的遍历--Reflect.ownKeys: ', Reflect.ownKeys(obj));
// 打印结果:
// 属性的遍历--Reflect.ownKeys: ['a', 'b', 'c', 'd', Symbol()]
}
/**
7. keys() / values() / entries() : 用于遍历对象 <与数组的 keys() / values() / entries() 用法相同, 可参考数组中的用法>
1. keys(): 对 键名 的遍历 。
2. values(): 对 键值 的遍历 。
3. entries(): 对 键值对 的遍历 。
*/
以上代码执行结果, 如图所示:
之前有整理过部分知识点, 现在将整理的相关内容, 验证之后慢慢分享给大家; 这个专题是 “前端ES6基础” 的相关专栏; 不积跬步,无以至千里, 戒焦戒躁 。