es6学习笔记之对象的扩展

一. 属性的简洁表示法

ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

var foo = 'bar' ; 
var baz = {foo};
baz // {foo : 'bar'}

//等同于
var baz = {foo : foo}

function f(x, y){
    return {x, y}
}

//等同于
function f(x, y){
    return { x : x, y : y};
}

f(1, 2) // object { x : 1, y : 2}

//方法也可以简写
var o = {
    method(){
          return "hello!" ; 
     }
  };

  //等同于
  var o = {
     method : function(){
            return "hello!" ;
          }
      };

var birth = '2000/01/01';
var person {
      name : '张三',
      //等同于birth : birth
      birth,
      //等同于hello : functon()....
      hello() {console.log(this.name)}
}

这种写法用于函数的返回值,将会非常方便。

function getPoint() {
    var x = 1;
    var y =10;
    return {x, y};
}

getPoint()
// { x : 1, y : 10}

二. 属性名表达式

obj . foo = true;
obj['a' + 'bc'] = 123;

如果使用字面量方式定义对象(使用大括号),在 ES5 中只能使用方法一(标识符)定义属性。

var obj = {
    foo : true,
    abc : 123
 };

ES6 允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内。

let propKey = 'foo';
let obj = { 
      [propKey] : true,
      ['a' + 'bc'] : 123
 };

var lastWord = 'last word';
var a = {
    'first word' : 'hello',
     [lastWord] : 'world'
  };
  a['first word'] // 'hello'
  a[lastWord] // 'world'
  a['last word'] // 'world'

表达式还可以用于定义方法名。

let obj = {
   ['h' + 'ello'](){
        return 'hi';
   }
};

obj.hello() // hi

属性名表达式与简洁表示法,不能同时使用,会报错。

//报错
var foo = 'bar';
var bar = 'abc';
var baz = { [foo] };

//正确
var foo = 'bar';
var baz  = {[foo] : 'abc'}

属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object],这一点要特别小心。

const keyA = { a : 1};
const keyB = { b : 2};

const myObject ={
    [KeyA] : 'valueA',
    [KeyB] : 'valueB'
};

三. Object.assign()

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

var target = { a : 1 };
var source1 = { b : 2 };
var source2 = { c : 3 };

Object.assignj(traget, souce1, source2);
target // {a : 1, b : 2, c : 3}

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

var target = {a : 1, b : 2};
var source1 = { b : 2, c : 2};
var source2 = { c : 3};

Objcet.assign(target, source1, source2);
target //{a : 1, b : 2, c :3}

//如果只有一个参数,Object.assign会直接返回该参数。

var obj = {a: 1};
Object.assign(obj) === obj // true

Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

var obj1 = {a : {b : 1}};
var obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

*Tips:源对象obj1的a属性的值是一个对象,Object.assign拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。*

//对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。

var target = {a : {b : 'c', d : 'e'}}
var source = {a : {b : 'hello'}}
Object.assign(target, source);
// {a : { b : 'hello'}}

Object.assign可以用来处理数组,但是会把数组视为对象。

Object.assign([1,2, 3], [4,5]);
//[4,5,3] 

//为属性指定默认值
const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
 };

 function processContent(options) {
    options = Object.assign({}, DEFAULTS, options);
    console.log(options);
    // ...
 }

四.属性的可枚举性和遍历

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

let obj = { foo : 123}; 
Object.getOwnPropertyDescriptor(obj, 'foo');
//{  
   // value : 123,
   // writable: true,
   //enumerable: true,
   //configurable: true
//}

描述对象的enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性。

目前,有四个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性。
Object.keys():返回对象自身的所有可枚举的属性的键名。
JSON.stringify():只串行化对象自身的可枚举的属性。
Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。

这四个操作之中,前三个是 ES5 就有的,最后一个Object.assign()是 ES6 新增的。其中,只有for...in会返回继承的属性,其他三个方法都会忽略继承的属性,只处理对象自身的属性。实际上,引入“可枚举”(enumerable)这个概念的最初目的,就是让某些属性可以规避掉for...in操作,不然所有内部属性和方法都会被遍历到。比如,对象原型的toString方法,以及数组的length属性,就通过“可枚举性”,从而避免被for...in遍历到。

另外,ES6 规定,所有 Class 的原型的方法都是不可枚举的。

ES6 一共有5种方法可以遍历对象的属性。

for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)。

Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)。

Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性。

Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是 Symbol 或字符串,也不管是否可枚举。

五. Object.keys(),Object.values(),Object.entries()

ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。

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

ES2017 引入了跟Object.keys配套的Object.values和Object.entries,作为遍历一个对象的补充手段,供for...of循环使用。

let {keys, values, entries} =  object;
let obj = { a : 1, b : 2, c : 3}

for(let key of keys(obj)){
    console.log(key);
    // 'a' , 'b' , 'c'
 }

for(let key of values(obj)){
    console.log(value);
    //1, 2, 3
}

   for(let [key, value] of entries(obj)){
      console.log([key, value]);
      //['a', 1], ['b', 2], ['c', 3]
   }

Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。

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

var obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj)
//["b", "c", "a"]

如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组。

Object.values('foo')
 // ['f', 'o', 'o']

Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

var obj = { foo : 'bar', baz : 42}
Object.entries(obj)
//[['foo', 'bar'], ['baz', 42]]

Object.entries方法的另一个用处是,将对象转为真正的Map结构。

var obj = { foo: 'bar', baz: 42 };
var obj = { foo: 'bar', baz: 42 };
map // Map { foo: "bar", baz: 42 }

六. 对象的扩展运算符

ES2017将扩展运算符(...)引入对象

1.解构赋值

let { x , y , ...z} = {x : 1, y : 2, a : 3, b : 4}

解构赋值必须是最后一个参数,否则会报错。
构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本。

let obj = { a : { b : 1}}
let {...x} = obj;
obj.a.b = 2;
x.a.b // 2

扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。

let z = { a : 3, b : 4}
let n = {...z}

n // { a: 3, b: 4 }

//等同于
let aClone = { ...a }
let aClone = Object.assign({}, a);

扩展运算符可以用于合并两个对象。

 let ab = {...a, ...b}
 //等同于
 let ab = Object.assign({}, a, b);

与数组的扩展运算符一样,对象的扩展运算符后面可以跟表达式。

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

推荐阅读更多精彩内容

  • 1.属性的简洁表示法 允许直接写入变量和函数 上面代码表明,ES6 允许在对象之中,直接写变量。这时,属性名为变量...
    雨飞飞雨阅读 1,136评论 0 3
  • 属性的简洁表示法 ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。 上面代码表明,ES6允...
    呼呼哥阅读 2,923评论 0 2
  • 三,字符串扩展 3.1 Unicode表示法 ES6 做出了改进,只要将码点放入大括号,就能正确解读该字符。有了这...
    eastbaby阅读 1,537评论 0 8
  • 17/21 周卫 河南【每日一结构】结构思考力21天思维改善训练营 G:【未来职业世界的三种人】媒体人、运营人、产...
    心理实践者周周阅读 136评论 0 0
  • 会很突然的想到自己就这样让日子过 竟然任凭日子这过了不然还能怎么样 不停的吵吵自己说给别人听停滞不前 不甘沉思调整...
    1OU阅读 335评论 0 1