ECMAscript
javascript 是 ECMAscript 的一种扩展语言 ECMAscript 提供了基础语言
浏览器环境: js = ECMAscript + BOM + DOM node环境: js = ECMAscript + fs + net + etc
对象结构赋值
const obj = {name: 'huahua', age: 19}
const name = 'jack'
const {name: reName = 'honghong', age} = obj
console.log(reName)
带标签的模板字符串
const a = '小明'
const b = '男'
const result = mtTag`hey, ${a} is a ${b}.`
function mtTag (strings, a, b) {
return strings[0] + a + strings[1] + b + strings[2]
}
可以用来处理函数中的变量,更好的输出函数
字符串包含
include、 startsWith、endsWith
函数剩余参数
function (a, ...args) {}
注:args只能使用一次,并放在最后
展开数组
const arr = ['fpp', 'bar', 'bas']
console.log.apply(console, arr)
console.log(...arr)
对象字面量
const obj = {
foo: 123,
[1 + 2]: 123
}
可以通过【】中填写js 表达式,作为对象的属性名
判断对象是否相等
Object.is(JSON.stringify({}), '{}')
可以用来判断+0 -0,NaN 是否相等
Proxy
用于创建一个对象的代理,从而实现基本操作的拦截和自定义
const person = {
name: 'xiaohua',
age: 20
}
const personProxy = new Proxy(person, {
get (target, property) { // 调取对应属性时
return property in target ? target[property] : 'default'
}
set (target, property, value) {
if (property === 'age') {
if (!Number.isInterger(value)) {
throw new TypeError(`${value} is no an int`)
}
}
target[property] = value
}
})
personProxy.age = 100
personProxy.gender = true
console.log(personProxy.name)
console.log(personProxy.xxx)
Reflect
对对象的操作
- Reflect.get(target, name, receiver)
- Reflect.set(target,name,value,receiver)
- Reflect.apply(target,thisArg,args)
- Reflect.construct(target,args[, newTarget])
- Reflect.defineProperty(target,name,desc)
- Reflect.deleteProperty(target,name)
- Reflect.has(target,name)
- Reflect.ownKeys(target)
- Reflect.preventExtensions(target)
- Reflect.isExtensible(target)
- Reflect.getOwnPropertyDescriptor(target, name)
- Reflect.getPrototypeOf(target)
- Reflect.setPrototypeOf(target, prototype)
const obj = {
name: 'xiaohui',
age: 18,
sex: '男'
}
console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))
类的继承
class Person {
constructor (name) {
this.name = name
}
say() {
console.log(`h1, my name is ${this.name}`)
}
}
class Student {
constructor (name, number) {
super(name)
this.number = number
}
hello () {
super.say()
console.log(`my school number is ${this.number}`)
}
}
const s = new student('jack', '100')
s.hello()
MAP类型
可以使用任意数据类型作为对象的键。
const m = new Map()
const tom = {name: 'tom'}
m.set(tom, 90)
console.log(m)
console.log(m.get(tom))
// m.has
// m.delete
// m.get(tom)
m.forEach((value, key) => {
console.log(value, key)
})
Symbol
主要避免对象,键的相同
const obj = {
[Symbol()]: 123
}
console.log(obj)
// 可以通过Symbol.for 传入相同的字符串名称,得到相同的值
Symbol.for('foo') === Symbol.for('foo') // TRUE
Symbol.for('true') === Symbol.for(true) // TRUE
for .. of
const s = new Set(['foo', 'bar'])
for(const item of s) {
console.log(item)
}
const m = new Map()
m.set('foo', '123')
m.set('bar', '345')
for(const item of m) {
console.log(item) // ['foo', '123'] ['bar', '345']
}
// 可以使用解构语法
for(const [key, value] of m) {
console.log(key, value) // 'foo', '123' 'bar', '345'
}
迭代器
通过迭代器可以不用关心,数据内部结构,直接遍历即可
const obj = {
name: ['张三', '李四', '王五'],
age: [18, 23, 19],
work: ['工人', '农民', '白领'],
each: (callback) => {
const all = [...this.name, ...this.age, ...this.work]
all.forEach(item => {
callback(item)
})
},
[Symbol.iterator]: * () => {
const all = [...this.name, ...this.age, ...this.work]
for (const item of all) {
yield item
}
}
}
// 外部即可通过 each方法, for.. of 调用,不必关心对象内部结构
for([key, value] of obj) {
console.log(key, value)
}
ES7新增
// Array.prototype.includes--------------------------
const arr = ['foo', 1, NaN, false]
console.log(arr.includes('foo'))
console.log(arr.includes(NaN)) // 可以直接计算NaN是否存在
// 指数运算符(等价)-----------------------------------------
console.log(Math.pow(2, 10))
console.log(2 ** 10)
ES8新增
- Object.value、Object.entires
- Object.getOwnPropertyDescriptors(), 完整复制属性
- String.padStart,String.padEnd // 可用于对齐字符串,排版
- 函数允许添加 尾逗号
for(const [key, value] of Object.entires(obj)) {
console.log(key, value)
}
const p1 = {
firstName: 'lei',
lastName: 'wang',
get fullName() {
retrun this.firstName + '' + this.lastName
}
}
const descriptiors = Object.getOwnPropertyDescriptors(p1)
const p2 = Object.defineProperties({}, descriptiors) // 完整复制
p2.firstName = 'zce'
console.log(p2.fullName)
// 结果 'zce wang'
const books = {
html: 5,
css: 16,
javascript: 128
}
for(const [name, count] of Object.entires(books)) {
console.log(`${name.padEnd(16, '-')}|${count.toString().padStart(3, '0')}`)
}
// 结果: html-------------|005
// css--------------|016
// javascript-------|128
ECMAscript 2020、2021
?.(可选链操作符)的使用
在对象具有多层级属性时,以前都使用.来连接。如:
var a = {}
console.log(a.b)
//如果a不存在b属性,则输出undefined
但如果层级多余2个的情况。如上述判断a.b.c是否存在
var a = {}
console.log(a.b.c)
//则会报a.b undefined的错误。
//这种情况很常见,以前常用做法是用短路语法一层层过滤下去
a && a.b && a.b.c
现在有了?.可选链操作符后就方便多了。可直接写
a?.b?.c
//如果不存在a.b.c就会返回undefined,不会报错(写成a.b?.c不会报错,因为a.b返回undefined)
?? 的使用
是es2020新增的空位合并操作符:
a??b
//如果a为null或undefined,则返回b,否则返回a。与||的区别在于??只对null和undefined返回b,对于‘’ 0 false之类的返回a
null ?? 1 // 1
undefined ?? 1 //1
NaN ?? 1 //NaN
0 ?? 1 //0
'' ?? 1 // ''
null || 1 //1
undefined || 1 //1
NaN || 1 //1
0 || 1 //1
'' || 1 //1