阮一峰ES6教程读书笔记(六)对象的新增方法

1. Object.is()

在ES6之前我们总是通过相等运算符==或者严格相等运算符===去判断两个值是否相等,但是这两者都有一定的缺陷。所以JavaScript缺乏一种运算,能够在所有环境中判断两个值是不是一样的,如果是一样的就应该相等。
ES6提出了同值相等算法,用来解决这个问题,该算法与===表现较为类似,不同之处在于比较+0-0和比较NaN与其自身:

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

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

在没有部署Object.is()方法的环境可以通过以下代码来部署该方法:

Object.defineProperty(Object, 'is', {
  value: function(x, y) {
    if (x === y) {
      // 针对+0 不等于 -0的情况
      return x !== 0 || 1 / x === 1 / y;
    }
    // 针对NaN的情况
    return x !== x && y !== y;
  },
  configurable: true,
  enumerable: false,
  writable: true
})

2. Object.assign()

Object.assign()主要用于对象的合并,其行为是将源对象的所有可枚举属性和方法添加到目标对象中。

const [target, source] = [{}, {name: 'bing', age: 23}]
Object.assign(target, source)

target // {name: 'bing', age: 23}

其行为与扩展运算符类似,不过扩展运算符是把所有的源对象的属性和方法都放到了一个新的对象中,但是Object.assign()是把源对象的属性和方法放到了目标对象中。

2.1 如果有同名属性

如果有同名属性,那么后面的属性会覆盖前面的属性值

let a = {name: 'bing'}
let b = {name: 'yan', age: 24}
let c = {name: 'can', age: 27}

Object.assign(a,b,c) // {name: "can", age: 27}

2.2 如果参数不是对象

严谨的来说,如果源对象参数不是对象,或者是特殊对象(正则表达式,Date对象等),那么该方法会直接跳过参数而不会报错

let a = new Date()
let b = {}

Object.assign(b, a) // {}

如果目标对象不是对象或者是特殊对象,那么会返回一个包装对象,当然undefinednull除外

Object.assign(null) // Cannot convert undefined or null to object
Object.assign(undefined) // Cannot convert undefined or null to object

// 下面的都会返回一个包装对象
Object.assign(NaN)
Object.assign(2)
Object.assign('string')

2.3 参数是数组的情况

因为数组也是一种对象,当使用该方法时,数组会被当做对象处理:

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

上述代码中因为目标数组中索引从0-3的位置都被原数组给覆盖了,所以返回的数组是[3, 4, 5, 6]

2.4 对取值函数的处理

Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。

const source = {
  get foo() { return 1 }
};
const target = {};

Object.assign(target, source)
// { foo: 1 }

上面代码中,source对象的foo属性是一个取值函数,Object.assign不会复制这个取值函数,只会拿到值以后,将这个值复制过去。

3. Object.getOwnPropertyDescriptors()

ES5 的Object.getOwnPropertyDescriptor()方法会返回某个对象属性的描述对象(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。

onst obj = {
  foo: 123,
  get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: get bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

上述代码中,使用该方法后反悔了一个对象,对象中包括了源对象的所有自身的属性的属性描述对象,该方法的出现主要是为了解决Object.assign无法拷贝getset,使用Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以实现正确拷贝。

onst source = {
  set foo(value) {
    console.log(value);
  }
};

const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')
// { get: undefined,
//   set: [Function: set foo],
//   enumerable: true,
//   configurable: true }

4. Object.setPrototypeOf()

ES6 推荐使用该方法设置原型对象,在某些时候我们想新生成一个对象使之继承现有对象的原型,我们可以采用以下方法:

// 方法一
const a = {name: 'bing'}
const b = a.constructor() // b继承了a的原型

// 方法二
const a = {name: 'bing'}
const b = {}
Object.setPrototypeOf(b, Object.getPrototypeOf(a))

5. Object.values()

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

const a = {name: 'bing'}
a.__proto__.age = 23  // 继承属性
Object.defineProperty(a, 'gender', {value: 'male', enumerable: false}) 
// 不可枚举属性

Object.values(a) // ["bing"] 只返回自身的可枚举属性

如果该方法的参数是一个字符串,那么将会得到令人惊喜的结果:

Object.values('string') // ["s", "t", "r", "i", "n", "g"]
[...'string'] // ["s", "t", "r", "i", "n", "g"]
Array.from('string') // ["s", "t", "r", "i", "n", "g"]

上述三种方法都能把一个字符串分解为包含字符的数组

6. Object.entries()

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

let obj = { one: 1, two: 2 };
for (let [k, v] of Object.entries(obj)) {
  console.log(
    `${JSON.stringify(k)}: ${JSON.stringify(v)}`
  );
}
// "one": 1
// "two": 2

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

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

Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。

Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }

该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。

参考链接

作者:阮一峰
链接:http://es6.ruanyifeng.com/#docs/destructuring

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

推荐阅读更多精彩内容

  • 1.属性的简洁表示法 允许直接写入变量和函数 上面代码表明,ES6 允许在对象之中,直接写变量。这时,属性名为变量...
    雨飞飞雨阅读 1,123评论 0 3
  • 一、概览 Object.is() Object.assign() Object.getOwnPropertyDes...
    HalShaw阅读 2,180评论 0 0
  • 属性的简洁表示法 ES6允许直接写入变量和函数,作为对象的属性和方法。 上面代码表明,ES6允许在对象之中,直接写...
    oWSQo阅读 498评论 0 0
  • 9.对象的扩展 1.属性的简洁表示法 es6允许直接写入变量和函数,作为对象的属性和方法--为了简洁 2.属性名表...
    安乐_f487阅读 497评论 0 0
  • Object.freeze() 该方法可以冻结一个对象,冻结对象指的是不能向这个对象,添加属性、删除属性、修改属性...
    秦声阅读 3,664评论 0 10