总结Es6对象扩展了哪些功能

前言

JavaScript中,几乎每一个值都是某种特定的类型对象,Es6也着重提升了对象的功能性,Es6通过多种方式来加强对象的使用,通过简单的语法扩展,提供更多操作对象及与对象交互的方法。下面来介绍它们。

对象字面量语法扩展

对象字面量如此就行,就是我们想创建对象,不在需要编写冗余的代码。直接通过的它的简洁语法就可以实现。那么看看Es6为对象做了那些特性吧。

属性初始值的简写

在Es5中,对象字面量只是简单的键值和集合,这意味着初始化属性有一些重复。

function person(name) {
    return {
        name: name
    }
}

在Es6中,通过属性的简写则可以省去这name属性一遍,当一个对象的属性和变量同名时,则可以省去冒号和值。看如下案例

function person(name) {
    return {
        name
    }
}

对象方法的简写语法

Es6也改进了对象字面量的对象简写方法,在Es5中,定义对象方法必须的得写完整名称才可以。

Es5案例

let person = {
    test: function() {}
}

Es6案例

let person() {
    test() {}
}

通过Es6对象的方法简写,定义的是一个匿名表达式,这个函数拥有和Es5一模一样的特性。Es5定义对象函数和Es6简写定义的函数唯一区别,简写的函数可以使用super

可计算属性名

在Es5中,如果想要通过计算得到属性名,则需要用[]方括号代替。

let person = {}
let value = "hello WaRen"
person["wa ren"] = "蛙人"
person[value] = "value"

上面example中,是我们在es5中的做法,如果对象的key值是一个变量,那我们就使用对象方括号添加。

在Es6中,可在对象字面量中使用可计算属性名称,我们来看下面例子

let key = "name"
let person = {
    [key]: "蛙人" // 在对象字面量中这样使用[]方括号定义key是Es6语法
    [`${key}_test`]: "test"
}

上面这种在对象字面量中使用方括号表示该属性名是可以计算的,可以写表达式的,然后最终key值都会以字符串类型返回。切记,在对象字面量中使用方括号[]定义key值是Es6中的语法。本人也是刚知道(基础不扎实 呜呜呜),经测试bable转换Es6转Es5可以看到结果。

重复的对象字面量属性

在Es5严格模式下加入了对象字面量重复属性的验证,当同时存在多个同名属性时会抛出异常。看下面例子

"use strict"
var person = {
    name: "蛙人",
    name: "张三" // 在Es5严格模式下会抛出语法错误
}

在Es5严格模式下时,第二个属性name会触发一个语法错误,但是在Es6中重复属性检查被移除了,Es6中无论是在严格模式下,还是不在严格模式下代码都不会进行重复属性验证,对于重复属性都是后面的覆盖前面的。ps: 这个我也是刚刚知道 流下了没技术的眼泪 。。。

"use strict"
let person = {
    name: "蛙人",
    name: "张三"
}

在上面example中,我们可以看到,这是Es6标准重复属性并没有抛出异常而是后面对象覆盖前面对象,最后name属性为"张三",我们现在浏览器运行的都是Es6标准。

Es6对象新增的方法

Es6中在全局Object对象上引入了一些新方法。

Object.is

我们在Es5中的时候经常使用== 相等运算符 or === 全等运算符来比较值,然而在Es5中相等运算符或者全等运算符也不完全准确,这里拿官网说的举个例子,+0和-0这个在JavaScript引擎中被表示两个不同的实体,而使用全等运算符或者相等运算符都会返回ture, 同样NaN == NaN返回false。然而Es6中出现了Object.is方法来弥补这些不足,Object.is方法接收2个参数,如果这两个参数值相等并且类型也相等,则返回true

console.log(+0 == -0) // ture
console.log(+0 === -0) // true
console.log(Object.is(+0, -0)) // false

console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(Object.is(NaN, NaN)) // true

console.log(10 == "10") // true
console.log(10 === "10") // false
console.log(Object.is(10, "10")) // false

上面example中,我们可以看到Object.is方法是挺严格的,但是这个只是处理特殊情况下使用,所以我们没必要抛弃== or ===

Object.assign

Object.assign方法可以接收任意数量源对象,第一个参数是接收者,也就是最终的返回值,第二个参数以后都是会复制到第一个参数里面,所以如果有多个源对象具有同名属性key值,那么则靠后的对象会覆盖靠前的对象。来看下面例子

let test1 = {
    name: "蛙人"
}
let test2 = {
    name: "张三"
}
let result = Object.assign({}, test1, test2)
console.log(result)  // {name: "张三"}

上面example中,可以看到上面的对象属性如果具有同名的,后面的则会覆盖前面的。如果参数里传入的是非对象也能执行,只不过会忽略。来看下面例子

let result = Object.assign({}, 1, 2, 3)
console.log(result)  // {}

注意: Object.assign方法不能将取值函数(访问器属性)复制到对象中,由于Object.assign方法执行了赋值操作,那么对象最终会转换成一个普通的属性。

let test = {
    get name() {
      return "蛙人"
    }
}
let result = Object.assign({}, test)
console.log(Object.getOwnPropertyDescriptor(result, "name")) // {configurable: true enumerable: true value: "蛙人" writable: true}

上面example中,可以看到我们复制对象的最终结果,取值函数确实丢失了,我们可以根据获取对象的描述属性可以看到。如果不懂对象的描述属性可以看我这篇文章《深入理解JavaScript对象》

Object.setPrototypeOf

在Es5中,提供了Object.getPrototypeOf方法获取对象的原型,然而Es5中并没有提供设置对象的原型的方法,如果我们想要设置对象的原型,xx.__proto__ = xx.__proto__ 显然这样写也是没问题的,但是并不合理。所以Es6提供了Object.setPrototypeOf方法, 这个方法接收两个参数,第一个就是被修改的对象,第二个是原型对象。来看下面例子

let person = {}
function Fn() {}
let fn = new Fn()
Object.setPrototypeOf(person, fn)
console.log(person)

上面example中,可以看到就是把person的原型对象修改成fn的原型对象,这时你在访问person对象就可以清楚的看到原型对象已经被更改了。

Object.values

Object.values方法返回一个数组,成员是参数对象自身的,不包含继承和原型上的

let person = {
    name: "蛙人",
    age: 24,
    sex: "male"
}
console.log(Object.values(person)) // ["蛙人", 24, "male"]

Object.entries

Object.entries方法返回一个数组(也就是一个二维数组),成员是参数对象自身的,属性的键值对数组,不包含继承和原型上的。

let person = {
    name: "蛙人",
    age: 24,
    sex: "male"
}
console.log(Object.entries(person)) // [["name", "蛙人"], ["age", 24], ["sex", "male"]]

Object.fromEntries

Object.fromEntriesObject.entries的反向操作,返回值是一个对象,用于将一个键值对数组转为对象。

let testArr = [
    ["name", "蛙人"],
    ["age", 24],
    ["sex", "male"]
]
console.log(Object.fromEntries(testArr)) // {name: "蛙人", age: 24, sex: "male"}

自有对象属性枚举顺序

在Es5中没有定义对象属性的枚举顺序,是由js引擎厂商自行决定的。然而,在Es6中规定了对象自有属性被枚举返回的顺序。自有属性枚举顺序的基本规则如下:

  • 所有数字键按升序排序
  • 所有字符串键按加入对象的顺序排序
  • 所有symbol键按加入对象的顺序排序
let o = {
    4: 4,
    1: 1,
    b: "b",
    a: "a"
}
o.c = "c"

console.log(Object.keys(o)) // ["1", "4", "b", "a", "c"]
console.log(Object.getOwnPropertyNames(o)) // ["1", "4", "b", "a", "c"]
for (let i in o) {
    console.log(i) // 1 4 b a c
}

上面example中,可以看到对象枚举属性都是根据Es6中规则顺序来返回的,请注意 ,对于数字键,尽管在对象字面量中顺序是随意的,但是在枚举时会被重新组合和排序。字符串紧跟数字键后面,并按照该属性在对象里的顺序返回,最后是动态添加字符串健值。

简化原型访问的Super引用

在Es6中,新提供了super关键字,该方法是为了简化获取当前的原型的对象使用的。来看下面例子

Es5案例

let person = {
    getName() {
      return Object.getPrototypeOf(this).getVal.call(this)
    }
}
let o = {
    getVal() {
      return "蛙人"
    }
}

Object.setPrototypeOf(person, o)
console.log(person.getName()) // 蛙人

上面example中,可以看到先把person的原型设置为o对象,然后调用person对象时,该getName方法里又获取了当前的原型,调用原型上的方法,也就是调用的o对象的方法。

Es6案例

let person = {
    getName() {
      return super.getVal.call(this)
    }
}
let o = {
    getVal() {
      return "蛙人"
    }
}

Object.setPrototypeOf(person, o)
console.log(person.getName()) // 蛙人

上面example中,可以看到我们把上面代码稍微调整了一下,把Object.getPrototypeOf换成了super关键字。super关键字作用就是可以代替Object.getPrototypeOf方法访问对象原型。但是super关键字也是有个弊端就是只能在对象字面量的方法简写情况下使用。来看下面案例

let person = {
    getName: function() {
      return super.toString() // 报错
    }
}

在上面example中,person对象里用匿名function定义了一个属性,由于在当前上下文中super引用是非法的,所以就抛出错误。那么为什么同样都是函数而有差异呢,那么我们继续往下看。

正确区分方法的定义

在Es6之前没有规定的方法这个概念,方法仅仅是一个具有功能而非对象的属性,而在Es6中正式将方法定义为一个函数,它会有一个内部的[[HomeObject]]属性来容纳这个方法从属的对象。看下面例子

let person = {
    getName() {} // 是方法
}
function getName() {} // 不是方法

上面example中,定义person对象,它有一个getName方法,由于直接把函数赋值给了person对象,getName方法的[[HomeObject]]属性值为person对象。然后在看下面用function关键字定义的getName方法,这时它没有赋值给一个对象,所以没有明确定义[[HomeObject]]属性。如果不使用super关键字这两个函数这点小区别没什么大问题。但是要使用super关键字的话就尤其重要。

因为super关键字引用都通过[[HomeObject]]属性来确定后续运行过程。super关键字先会在[[HomeObject]]属性上找到当前对象(属性值),也就是person然后在调用Object.getPrototypeOf方法获取当前原型, 然后在去原型上找到当前同名函数,最后设置this绑定并且调用。这也就是上面为什么super关键字会报错的原因。

觉得写的不错的话那就点个赞叭!


大家也可以加我的微信一起交流 这里

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

推荐阅读更多精彩内容