ES6 对象扩展

一、对象属性的简洁写法
1、属性简写

var foo = "bar";
var baz = { foo };
baz; // { foo: "baz" }
// 等价于
var baz = { foo: foo };

function f(x, y) {
  return { x, y };
// 等价于: return { x: x, y: y };
}
f(1, 2); // {x: 1, y: 2}

2、方法简写

var obj = {
  method() {
    return "yuan is an animal";
  }
}
// 等价于
var obj = {
  method: function() {
    return "yuan is an animal";
  }
}

二、属性名表达式
在ES5中,定义对象的属性有两种方法

// 方法一:标识符作为属性名
obj.foo = true;
// 方法二:表达式作为属性名
obj["foo"] = true;

如果使用字面量方式定义对象,在ES5中只能使用方法一,而在ES6中可以使用方法二:

let yuan = "monkey";
let animal = {
  "type": "animal",
  [yuan]: "yuan is not monkey"
}
animal["type"]; // "animal"
animal[yuan]; // "yuan is not monkey"
animal["monkey"]; // "yuan is not monkey"

属性名定义方法:

let monkey = {
  ['yuan']() {
    return "yuan is a monkey";
  }
}
monkey.yuan(); // yuan is a monkey"

三、方法的name 属性
对象中的方法,也具有类似 function 的 name 属性:

let monkey = {
  ['yuan']() {
    return "yuan is a monkey";
  }
}
monkey.yuan.name; //  "yuan"

其他的用法同“ES6函数扩展”的 name 属性用法类似。
四、Object.is()
因在ES5中,并不能处理比较两个值是否严格相等,对于NaN,+0,-0等并不能做出严格相等来判断。
Object.is() 这个方法就是来弥补上述的缺陷的:

+0 === -0; // true
NaN === NaN; // false

Object.is(+0, -0); // false
Object.is(NaN, NaN); // true

五、Object.assign()
1、基本用法
定义:将源对象(sourceN,不知一个源对象)的所有可枚举属性复制到目标对象上(target)。
使用方式:Object.assign(target, source1, source2, ..., sourceN)

let target = { x: 1};
let s1 = { y: 2 };
let s2 = { z: 3 };
Object.assign(target, s1, s2); // {x: 1, y: 2, z: 3}

2、注意点
(1)、如果目标对象与源对象用同名属性,或多个源对象具有同名属性,则后面的属性会覆盖前面的属性:

let target2 = { x: 1};
let s3 = { x: 3, y: 2 };
let s4 = { y: 4,  z: 3 };
Object.assign(target2, s3, s4); // {x: 3, y: 4, z: 3}

(2)如果参数不是对象,则会先转成对象,在返回:

typeof Object.assign(3); // "object"

(3)、若参数中有undefined 或者 null,这两个参数不能放在目标对象的位置,否则会报错:

Object.assign(undefined); // Cannot convert undefined or null to object at Function.assign (<anonymous>)
Object.assign(null); // Cannot convert undefined or null to object at Function.assign (<anonymous>)

(4)、除了字符串会以数组的形式复制到目标对象上,其他值都不会产生效果:

let a1 = 'yuan';
let a2 = true;
let a3 = 11;
let a4 = NaN;
Object.assign({}, a1, a2, a3, a4); // {0: "y", 1: "u", 2: "a", 3: "n"}

(5)、Object.assign()这个方法是对对象引用的复制,即是浅复制,而不是深复制。这里需要规避同名属性替换带来的问题:

var obj1 = { a: { b: 3, c: 4 } };
var obj2 = { a: { b: "yuan" } } ;
Object.assign(obj1, obj2); // { a: { b: "yuan" } }
obj1.a.b; // "yuan"

3、基本用途
(1)、给对象添加属性

class Geo {
  constructor(x, y) {
   Object.assign(this, x, y); 
  }
}

(2)、给对象添加方法

Object.assig(SomeClass.prototype, {
  someMethod(arg1, arg2) { ... },
  anotherMethod() { ... }
})

(3)、克隆对象

function clone(originObj) {
  return Object.assign({}, originObj); // 将原始对象复制给空对象
}

(4)、合并多个对象

const mergeObjs = {
  (target, ...sources) => Object.assign(target, ...sources);
}

(5)、为属性指定默认值

const DEFAULTS = {
  logleve: 0,
  outputFormat: 'html'
};
function processContent(options) {
 retrun Object.assign({}, DEFAULTS, options);
}

六、属性的可枚举性(Enumerable)
ES5 中有3个操作会忽略 Enumerable 为 false 的属性:
1、for...in 循环:只遍历对象自身的和继承的可枚举性。
2、Object.keys():返回对象自身的所有可枚举属性的键名。
3、JSON.stringify():只串行化对象自身的可枚举属性。
在ES6 中,Object.assign() 操作会忽略 Enumerable 为false 的属性。
在上面四个操作中,只有 for...in 操作会返回继承的属性,为了不使问题复杂化,只关心对象自身的属性。所以,尽量不要使用 for...in 循环,用 Object.keys() 代替。
ES6还规定,所有 Class 的原型的方法都是不可枚举的。
七、属性的遍历
在ES6 中有五种方法来遍历对象的属性:
1、for...in
返回对象自身的和继承的可枚举属性(不含 Symbol 属性)。
2、Object.keys(ob)
返回一个数组,包括对象自身的(不含继承)所有可枚举属性(不含 Symbol 属性)。
3、Object.getOwnPropertyNames(obj)
返回一个数组,包括自身的所有属性(不含Symbol属性,但包括不可枚举属性)。
4、Object.getOwnPropertySymbols(obj)
返回一个数组。包含对象自身的所有 Symbol 属性。
5、Object.ownKeys(obj)
返回一个数组,包含对象所有的属性.。
以上五种方法都遵循同样的遍历顺序:
(1)、首先遍历所有属性名为数值的属性,按数字排序;
(2)、其次遍历所有属性名为字符串的属性,按照生成时间排序;
(3)、最后遍历所有属性名为 Symbol 的属性,按照生成时间排序。
八、Object.keys(),Object.values(),Object.entries()
1、Object.keys(obj)
返回一个数组,是由参数对象自身的(不含继承)所有可遍历属性的键名:

/* Array 对象 */ 
let arr = ["a", "b", "c"];
console.log(Object.keys(arr)); 
// ['0', '1', '2']

/* Object 对象 */ 
let obj = { foo: "bar", baz: 42 }, 
    keys = Object.keys(obj);
// CCAC: Chrome Console Auto Copy
copy(keys); 
// ["foo","baz"]

/* 类数组 对象 */ 
let obj = { 0 : "a", 1 : "b", 2 : "c"};
console.log(Object.keys(obj)); 
// ['0', '1', '2']

// 类数组 对象, 随机 key 排序 (遵循上述的属性的遍历顺序)
let anObj = { 100: 'a', 2: 'b', 7: 'c' }; 
console.log(Object.keys(anObj)); 
// ['2', '7', '100']

/* getFoo 是个不可枚举的属性 */ 
var my_obj = Object.create(
   {}, 
   { getFoo : { value : function () { return this.foo } } }
);
my_obj.foo = 1;

console.log(Object.keys(my_obj)); 
// ['foo']

2、Object.values(obj)
返回一个数组,是由参数对象自身的(不含继承)所有可遍历属性的键值:

var obj = { foo: "bar", baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// 类数组对象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

// 随机键值的类数组对象 (遵循上述的属性的遍历顺序)
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

// getFoo 是不可枚举属性
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = "bar";
console.log(Object.values(my_obj)); // ['bar']

// 参数是非对象会转变成对象
console.log(Object.values("foo")); // ['f', 'o', 'o']

Object.values() 会过滤属性名为 Symbol 值的属性:

Object.values({ [Symbol() ]: 123, "foo": "faa"}) // ["faa"]

3、Object.entries(obj)
返回一个数组,是由参数对象自身的(不含继承)所有可遍历属性的键值对数组:

const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

// 类数组对象
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

// 随机键值的类数组对象 (遵循上述的属性的遍历顺序)
const anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]

// getFoo 是不可枚举属性
const myObj = Object.create({}, { getFoo: { value() { return this.foo; } } });
myObj.foo = 'bar';
console.log(Object.entries(myObj)); // [ ['foo', 'bar'] ]

// 参数是非对象会转变成对象
console.log(Object.entries('foo')); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]

// 优雅地遍历键值
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}

Object.entries() 的另一个用处:将对象转为真正的Map 数据结构:

var obj = { foo: "bar", baz: 42 }; 
var map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }

结语:
1、本章重点在理解Object.keys(),Object.values(),Object.entries() 三个方法的使用以及Object.assign 的用法
2、属性在ES6中属性的简写与属性名的表达式
3、了解ES6中五种遍历属性的方法及其区别

戳我博客

章节目录

1、ES6中啥是块级作用域?运用在哪些地方?
2、ES6中使用解构赋值能带给我们什么?
3、ES6字符串扩展增加了哪些?
4、ES6对正则做了哪些扩展?
5、ES6数值多了哪些扩展?
6、ES6函数扩展(箭头函数)
7、ES6 数组给我们带来哪些操作便利?
8、ES6 对象扩展
9、Symbol 数据类型在 ES6 中起什么作用?
10、Map 和 Set 两数据结构在ES6的作用
11、ES6 中的Proxy 和 Reflect 到底是什么鬼?
12、从 Promise 开始踏入异步操作之旅
13、ES6 迭代器(Iterator)和 for...of循环使用方法
14、ES6 异步进阶第二步:Generator 函数
15、JavaScript 异步操作进阶第三步:async 函数
16、ES6 构造函数语法糖:class 类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270