一 对象成员 的扩展
1. 对象成员 的简洁写法
属性
- const foo = bar;
- const result = {foo};
- // 上式 等同于:
- const foo = bar;
- const result = {foo: foo};
方法
- const o = {
- method() {
- return "Hello!";
- }
- };
- // 上式 等同于
- const o = {
- method: function() {
- return "Hello!";
- }
- };
2. 自定义创建对象时, 属性名 可以是 动态表达式
举例说明:
- // 如下: ES6 支持; ES5 不支持
- let lastWord = last word;
- const a = {
- first word: hello,
- [lastWord]: world
- };
注意区分:
ES5ES6 都支持给 已创建好的对象 添加属性时, 属性名为动态表达式
ES5 不支持在 自定义创建对象时, 为对象添加 动态表达式的属性
ES6 支持在自 自定义创建对象时, 为对象动态添加属性
- // 如下: ES5 ES6 都支持
- let obj = {};
- const aa = name;
- obj[aa] = zhang;
约束: 属性名表达式与简洁表示法, 不能同时使用, 会报错
- // 报错
- const foo = bar;
- const bar = abc;
- const baz = { [foo] };
- // 正确
- const foo = bar;
- const baz = { [foo]: abc};
二 对象的 扩展运算符
1. 作用: 取出对象中 自身 可枚举的非继承 的属性
- let z = { a: 3, b: 4 };
- let result = { ...z };
- console.log(result); // { a: 3, b: 4 }
2. 扩展运算符 结合 解构赋值
结构赋值时, 尚未被读取的属性, 都会被分配到指定的对象上面
- let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
- console.log(x); // 1
- console.log(y); // 2
- console.log(z); // { a: 3, b: 4 }
解构赋值不是最后一个参数, 所以会报错
- let { ...x, y, z } = obj; // 句法错误
- let { x, ...y, ...z } = obj; // 句法错误
解构赋值是 浅拷贝; 不复制 原型上的属性
- let o2 = { b: 2 };
- o2.__proto__ = o1;
- let { ...o3 } = o2;
- o3 // { b: 2 }
3. 等同于 Object.assign( ) : 对象属性拷贝合并(浅拷贝)
重名属性, 后者覆盖前者
- let result = { ...a, ...b };
- // 等同于
- let result = Object.assign({}, a, b);
不能用于对象的 深拷贝: 对象的属性如果是对象, 则为属性对象的 浅拷贝: 只是拷贝了 属性对象的指针
- const a = {
- name: zhang,
- info: {
- age: 18
- }
- };
- const aClone = {...a};
- a.name = xin;
- a.info.age = 20;
- console.log(aClone); // aClone.name 值为 zhang;aClone.info.age 值为 20
三 对象的合并: Object.assign( )
1. 语法
Object.assign(target, source1, source2)
参数 target: 目标对象
参数 source1 source2: 源对象
返回值: 合并了 源对象属性的 目标对象指针
2. 作用: 对象属性的合并
将源对象 所有可枚举的非继承的属性, 合并到 目标对象中
如果 目标对象 与 源对象 有同名属性源对象 与 源对象 有重名属性: 后者覆盖前者
3. 对象的属性如果是对象, 则为属性对象的 浅拷贝: 只是拷贝了 属性对象的指针
如果 源对象 某个属性的值是对象, 那么目标对象拷贝, 得到的是这个对象的引用
- const a = {age: 20};
- const b = {
- info: {
- name: zhang,
- sex: man
- }
- };
- const result = Object.assign(a, b);
- console.log(result.info === b.info); // true
注意: Object.assign( ) 不能用于对象的深拷贝, 举例如下
- const a = {
- name: zhang,
- info: {
- age: 18
- }
- };
- const aClone = Object.assign({}, a);
- console.log(a === aClone); // 输出 false; 但改变了 a.info 中的属性; aClone.info 中的属性也会变化
4. 如果参数不是对象, 会被默认转成对象(了解)
如果参数不是对象, 会默认将参数转为对象(但 null / undefined 不能转为对象)
参数 target:(目标对象)
若 值为 null / undefined, 会直接报错
若值为 string 类型: 会将字符串转为包装对象(数组形式); ab 变为
[0: a, 1: b]
若值为 Number 类型: 会将 数值 转为包装对象
若值为 Boolean 类型: 会将 布尔值 转为包装对象
参数 source1:(源对象)
若 值为 null / undefined, 会跳过, 不报错
若值为 string 类型: 会将字符串转为包装对象(数组形式); ab 变为
[0: a, 1: b]
若值为 Number 类型: 会被忽略
若值为 Boolean 类型: 会被忽略
四对象的遍历: Object.keys( )Object.values( )Object.entries( )
1. ES5 引入 Object.keys( )
作用: 遍历 自身 可枚举的非继承的属性 的 键值
语法:
Object.keys(obj)
参数: 要遍历的对象
返回值: 对象 键名 构成的 一维数组(键名)
- var obj = { foo: bar, baz: 42 };
- console.log(Object.keys(obj)); // ["foo", "baz"]
2. ES6 补充 Object.values( )
作用: 遍历 自身 可枚举的非继承的属性 的 键值
语法:
Object.values(obj)
参数: 要遍历的对象
返回值: 对象 键值 构成的 一维数组(键值)
- var obj = { foo: bar, baz: 42 };
- console.log(Object.values(obj)); // ["bar", 42]
3. ES6 补充 Object.entries( )
语法:
Object.values(obj)
参数: 要遍历的对象
返回值: 对象 键值 构成的 二维数组(键名 键值)
- const obj = { foo: bar, baz: 42 };
- console.log(Object.entries(obj)); // [ ["foo", "bar"], ["baz", 42] ]
作用: 遍历 自身 可枚举的非继承的属性 的 键名键值
遍历对象
将对象转为真正的 Map 结构
- const obj = { foo: bar, baz: 42 };
- const map = new Map(Object.entries(obj));
- map // Map { foo: "bar", baz: 42 }
4. 遍历 对象属性 的方法汇总
(1)遍历对象属性 的几种方法:
for...in: 遍历 对象属性 (含: 可枚举的继承的; 不含: Symbol 类型的)
Object.keys(obj) Object.values(obj) Object.entries(obj): 返回一个数组;(含: 可枚举的; 不含: 继承的 Symbol 类型的)
Object.getOwnPropertyNames(obj)
: 返回一个键名数组;(含: 可枚举的不可枚举的; 不含: 继承的 Symbol 类型的)
Object.getOwnPropertySymbols(obj)
: 返回一个 Symbol 键值的数组;(只含: Symbol 类型的)
Reflect.ownKeys(obj)
: 返回一个数组, (含: 除继承外的 所有属性, 无论 是否可比遍历无论 Symbol 类型; 不含: 继承的)
(2)遍历对象属性的顺序: 以上五种方法都遵循, 如下
首先遍历所有数值键, 按照数值升序排列
其次遍历所有字符串键, 按照加入时间升序排列
最后遍历所有 Symbol 键, 按照加入时间升序排列
五对象属性的 底层描述
1. 回顾: 获取对象属性 的描述对象
Object.getOwnPropertyDescriptor(obj, property)
对象的每个属性都有一个描述对象(Descriptor), 用来控制该属性的行为
Object.getOwnPropertyDescriptor(obj, property)
方法来 获取对象属性 的描述对象
- const obj = { foo: 123 };
- const result = Object.getOwnPropertyDescriptor(obj, foo);
- console.log(result);
- // {
- // value: 123, // 属性值
- // writable: true, // 可写性: 是否可修改
- // enumerable: true, // 可枚举性: 是否可枚举
- // configurable: true // 可配置性: 是否可以用 delete 删除
- // }
2. 回顾: 给对象添加属性 和 属性的描述信息
Object.defineProperty(obj, property, descriptor)
语法:
参数 1: 要添加属性的对象
参数 2: 要添加属性的键值
参数 3: 要添加属性的描述信息
- var obj = {};
- Object.defineProperty(obj, "a", {
- value : 1,
- writable : true,
- configurable : true,
- enumerable : true
- });
- // 如上代码, 等同于:
- var o = {};
- o.a = 1;
3. 回顾: 判断对象的属性 是否是继承的 / 自身提供的
myObject.hasOwnProperty(property)
语法:
参数: 要判断的属性
返回值: 布尔值(true: 对象自身属性; false: 对象继承属性)
4. 回顾: 对象属性的 可枚举性
Object.getOwnPropertyDescriptor(obj, property).enumerable
查看对象的属性是否 可枚举
- console.log(Object.getOwnPropertyDescriptor([], length).enumerable);
- // false
4 个操作: 会忽略 enumerable 为 false 的属性
for...in : 遍历 对象自身可枚举继承 的属性(含继承不含 Symbol 属性)
扩展运算符 ... : 遍历 对象自身可枚举属性(不含继承)
Object.keys(): 遍历 对象自身可枚举属性(不含继承 不含 Symbol 属性)
JSON.stringify(): 只串行化 对象自身可枚举的属性(不含继承)
Object.assign(): 拷贝 对象自身可枚举属性(不含继承)
5. 回顾: 判断属性是否是 对象自身的 并且 可枚举
maObject.propertyIsEnumerable(property)
返回值: 只有属性 既是自身属性, 又可枚举, 才返回 true
6. ES6: 获取对象所有自身 (不含继承) 属性 的描述对象
- Object.getOwnPropertyDescriptors const obj = {
- foo: 123,
- get bar() {
- return abc
- }
- };
- const result = Object.getOwnPropertyDescriptors(obj) console.log(result);
- // { foo:
- // { value: 123,
- // writable: true,
- // enumerable: true,
- // configurable: true },
- // bar:
- // { get: [Function: get bar],
- // set: undefined,
- // enumerable: true,
- // configurable: true } }
六对象原型 操作方法
1. __proto__ 获取对象的原型对象: 只有浏览器广泛支持(不推荐使用)
声明: 该属性没有写入 ES6 的正文, 标准明确规定, 只有浏览器必须部署这个属性, 其他运行环境不一定需要部署; 所以在实际开发中不要使用该属性
语法: obj.__proto__ 可以获取 obj 对象的原型对象
2. ES6 设置 原型对象
Object.setPrototypeOf(object, prototype)
语法:
参数 1: 被操作对象
参数 2: 原型对象
返回值: 被操作对象本身
- let proto = {};
- let obj = { x: 10 };
- Object.setPrototypeOf(obj, proto);
- proto.y = 20;
- proto.z = 40;
- obj.x // 10
- obj.y // 20
- obj.z // 40
规定:
如果第一个参数不是对象, 会自动转为对象; 由于返回的还是第一个参数, 所以这个操作不会产生任何效果
若第一个参数是 undefined 和 null(无法转成对象), 会报错
- Object.setPrototypeOf(1, {}) === 1 // true
- Object.setPrototypeOf(foo, {}) === foo // true
- Object.setPrototypeOf(true, {}) === true // true
- Object.setPrototypeOf(undefined, {}); // 报错
- Object.setPrototypeOf(null, {}); // 报错
3. ES6 获取 原型对象
Object.getPrototypeOf(object)
语法:
参数: 操作对象
返回值: 操作对象 的 原型对象
七关键字 super --- 指向 当前对象的原型对象(2 个使用约束条件)
关键字 super: 指向当前对象的原型对象
约束:
只能用在 对象的 简写 方法 之中, 目前 super 在其他地方都会报错
- // 正确用法
- const obj = {
- find() {
- return super.foo;
- }
- };
- // 以下三种情况, 都不允许, 会报错
- const obj = {
- foo: super.foo // 报错: super 用在了对象的属性中
- }
- const obj = {
- foo: () => super.foo // 报错: super 用在了函数中, 又将这个函数定义成对象的方法
- }
- const obj = {
- foo: function () {
- return super.foo // 报错: super 用在了函数中, 又将这个函数定义成对象的方法
- }
- }
八 比较 任意数据类型的值 是否相等: Object.is( )
ES6 提出: "Same-value equality" 的原则, 对比较两个值是否相等, 做了更严格的规范
语法:
参数 1, 参数 2: 要比较是否相等的两个值 Object.is(a, b)
返回值: 布尔值
对比:
ES6 中的比较方法 Object.is( ) :NaN 等于 NaN;-0 不等于 +0
ES5 中的比较方法 == === :NaN 不等于 NaN;-0 等于 +0;== 会发生隐式转换
来源: http://www.bubuko.com/infodetail-2502862.html