锋利的ES6 — 对象API

  1. assign(ES6)
  2. is(ES6)
  3. entries(ES2017)
  4. fromEntries(ES2019草案)
  5. defineProperty、defineProperties(ES6)

锋利的ES6 系列文章介绍ES6(ES5+)中新增的比较好用的新特性。本篇聊聊对象的API并对todolist做一个重大更新,文末附有Git地址。



assign(ES6)

合并多个对象

1
2
3
4
5
6
7
8
const target = { a: 1, b: 2 }
const source = { b: 4, c: 5 }

const returnedTarget = Object.assign(target, source)

console.log(target) // { a: 1, b: 4, c: 5 }

console.log(returnedTarget) // { a: 1, b: 4, c: 5 }

在我们的todolist案例中,添加待办事项的地方可以稍作改造

1
2
3
4
5
6
var todo = {
title: title,
time: time
}
todo.id = Date.now()
todo.hasFinish = false

可以改为:

1
2
3
4
5
6
7
8
var todo = {
title: title,
time: time
}
todo = Object.assign({}, todo, {
id: Date.now(),
hasFinish: false
})

当然,在开发中这样的改造其实意义并不大,只不过为了让朋友们更好理解这个方法。

is(ES6)

判断两个值是否相等,甚至可以直接判断两个NaN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Object.is('foo', 'foo')     // true
Object.is(window, window) // true

Object.is('foo', 'bar') // false
Object.is([], []) // false

var foo = { a: 1 }
var bar = { a: 1 }
Object.is(foo, foo) // true
Object.is(foo, bar) // false

Object.is(null, null) // true

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

entries(ES2017)

返回键值对数组,跟for…in的顺序一致

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

fromEntries(ES2019草案)

将键值对数组转换成对象

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

defineProperty、defineProperties(ES6)

给对象定义新属性或者修改现有属性

1
2
3
4
5
6
7
var obj = {}
Object.defineProperty(obj, "name", {
enumerable: false, // 配置不可枚举,name属性就不能通过 for...in 遍历到
configurable: false, // 配置不可被删除,name不能通过delete运算符删除
writable: false, // 配置不可写,属性不能被重新赋值或修改
value: "dary" // 属性值为dary
})

defineProperties 跟defineProperty的作用是一样的,它可以一次定义多个属性,每个属性里的配置项都一样使用即可

1
2
3
4
5
6
7
8
9
10
11
var obj = {};
Object.defineProperties(obj, {
'name': {
value: 'dary',
writable: true
},
'age': {
value: 19,
writable: false
}
});

但是,这里要说的不仅是这个用法,还有defineProperty 的另外一个更高级的用法,那就是getset

1
2
3
4
5
6
7
8
9
10
var obj = {}
var v = undefined
Object.defineProperty(obj, "name", {
get: function () {
return v
},
set: function (value) {
v = value
}
})

我们可以在第三个参数里写getset,这两个方法分别会在我们获取obj的name属性值和设置obj的name属性时被调用。

  • 当我们获取obj.name的时候实际上取到的是get的返回值
  • 当我们给obj.name属性赋值的时候,赋的值就是set方法的参数value,我们在set方法里把value赋值给v,这样再次获取obj.name的时候得到的就是我们刚刚赋的值了

那么,这个东西有什么用呢?其实非常有用,我们可以在set方法里面写一些自己的代码,比如:

1
2
3
4
5
6
7
8
9
10
11
var obj = {}
var v = undefined
Object.defineProperty(obj, "name", {
get: function () {
return v
},
set: function (value) {
v = value
console.log('obj.name is setted')
}
})

defineProperty

这个时候我们可以看到,每当我们给obj.name赋值的时候都会打印obj.name is setted,也就是说我们可以把obj.name 属性值发生变化时要做的操作放在set方法里,这样就会变得非常方便,比如我要把obj.name渲染到页面上,代码可以这么写了

HTML

1
<h1></h1>

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var obj = {}
var v = 'dary'
Object.defineProperty(obj, "name", {
get: function () {
return v
},
set: function (value) {
v = value
renderMain()
}
})
renderMain()
function renderMain () {
document.querySelector('h1').innerHTML = v
}

控制台运行截图

我们再尝试修改obj.name的属性值

修改之后的截图

我们可以看到,只需要修改属性值页面会自动完成渲染,十分方便。

这样的做法我们可以移植到todolist案例中

1
2
3
4
5
6
7
8
9
10
11
var obj = {}
Object.defineProperty(obj, 'todos', {
get () {
return todos
},
set (value) {
todos = value
// 每一次todos被修改都调用render方法
render()
}
})

至此,我们把代码中的todos都改成obj.todos,并且只需要在页面初始调用一次render(),其他地方的渲染都会在set方法里直接运行,不需要每次调用。

这样我们就可以集中精力在我们的业务逻辑上而不用担心页面渲染了

但是,现在我们会发现一个问题,就是添加事项添加不上了,因为我们原本用的是

1
todos.push(todo)

push修改的是源数组,这样并不会触发objset方法,解决方案如下:

1
obj.todos = obj.todos.concat([todo])

todolist(待办事项列表)案例将在我的github上持续更新

地址:https://github.com/dary1112/todolist.git

欢迎star!!!


代码不是万能的,但不写代码是万万不能的

Dary记


  • 更多干货,尽在公众号



转载请注明来源,文末有原始链接。欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 dary1112@foxmail.com

创作不易,您的打赏是我更新的动力

  • 支付宝

  • 微信

文章标题:锋利的ES6 — 对象API

文章字数:1.2k

本文作者:Dary

发布时间:2020-03-16, 14:56:00

最后更新:2020-03-16, 18:14:03

原始链接:http://www.xiongdalin.com/2020/03/16/ES6-object/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录