参考答案:
ES 全称是ECMAScript,它是JavaScript基础构建的一种语言,JavaScript正是建立在ECMAScript语言的基础规范中建立使用的,那么,ECMAScript的使用,对于JavaScript至关重要!
在我的理解中,ECMAScript是一种语言层面的东西,它只是定义了JavaScript以及在它基础之上建立的其他语言的语法规范,而JavaScript的语言,更关于一种平台性质在其中。
JavaScript包括 ECMAScript、DOM、BOM三个组成部分,DOM和BOM是web API提供的接口或者是JavaScript和浏览器之间进行交互的部分,实质就是操纵文档元素,进行展示布局,而ECMAScript在JavaScript中其中语法的作用,它不会去跟文档有直接的关系,但是他的数据处理完成后会通过web API展示在文档中。
新特性主要归为四大类:
比如let 和 const 的块级作用域
比如解构、展开、参数默认值、模板字符串
比如promise、proxy、object的assign、is
比如symbol、set、map
下面具体进行介绍
1//块级作用域一级块级作用域的使用 2if (true) { 3 const param = 'param in if block' 4 console.log(param) //param in if block 5} 6console.log(param) //块级作用域外访问内部定义的变量,ReferenceError: param is not defined
1// 暂时性死区 2const i = 100 3if (i) { 4 console.log(i) //ReferenceError: Cannot access 'i' before initialization 5 const i = 1000 6}
1 2 // const常量声明必须初始化 3 const i; 4 i = 10; 5 console.log(i) //SyntaxError: Missing initializer in const declaration 6
1// 基本类型常量不能修改,引用类型常量能修改属性 2const str = 'str' 3str = 'str1' //TypeError: Assignment to constant variable. 4 5const arr = [1, 2, 3] 6arr[0] = 100 7console.log(arr[0]) //100
声明方式 | 变量提升 | 作用域 | 初始值 | 重复定义 |
---|---|---|---|---|
var | 是 | 函数级 | 不需要 | 允许 |
let | 否 | 块级 | 不需要 | 不允许 |
const | 否 | 块级 | 必需 | 不允许 |
数组解构
单独解构-根据数组索引,将数组解构成单独的元素
1const arr = [1, 2, 3] 2 3const [a, b, c] = arr 4console.log(a, b, c) //1,2,3 5const [, , d] = arr 6console.log(d) //3
1const arr = [1, 2, 3] 2 3const [, , , defaultVal = '4'] = arr 4console.log('设置默认值', defaultVal)
1const arr = [1, 2, 3] 2 3const [e, ...rest] = arr 4console.log(rest) //[2, 3]
1// 拆分字符串 2const str = 'xiaobai/18/200' 3const strArr = str.split('/') 4const [, age] = strArr 5console.log(age) //18
对象解构
单个/多个解构-跟数组解构差不多
1const obj = { name: 'xiaohui', age: 18, height: undefined } 2const { name, age } = obj 3console.log(name, age) // 'xiaohui', 18
1const obj = { name: 'xiaohui', age: 18, height: undefined } 2const { name: objName } = obj 3console.log(objName)
1const obj = { name: 'xiaohui', age: 18, height: undefined } 2const { next = 'default' } = obj 3console.log(next)
用法:使用``将字符串包裹起来
功能:可以换行、插值、使用标签函数进行字符串操作
示例:
1//换行 2const str = `fdsjak 3 fdsa` 4console.log(str) 5 6// 插值 7const strs = `random: ${Math.random()}` 8console.log(strs)
1/** 2 * 字符串模板函数 3 * @param {array} strs 以插值为分隔符组成的字符串数组 4 * @param {string} name 插值的value,有多少个就会传入多少个 5 */ 6const tagFunc = (strs, name, gender) => { 7 const [str1, str2, str3] = strs 8 const genderParsed = gender == '1' ? '男' : '女' 9 // 可以在此做过滤,字符串处理,多语言等操作 10 return str1 + name + str2 + str3 + genderParsed 11} 12 13// 带标签的模板字符串, 14const person = { 15 name: 'xiaohui', 16 gender: 1, 17} 18// 返回值为标签函数的返回值 19const result = tagFunc`my name is ${person.name}.gender is ${person.gender}` 20console.log(result) //my name is xiaohui.gender is 男
1const str = 'abcd' 2 3console.log(str.includes('e')) //false 4console.log(str.startsWith('a')) //true 5console.log(str.endsWith('a')) //false
1// 带默认参数的形参一般放在后面,减少传参导致的错误几率 2const defaultParams = function (name, age = 0) { 3 return [age, name] 4} 5console.log(defaultParams(1))
1// 剩余参数,转化成数组 2const restParams = function (...args) { 3 console.log(args.toString()) //1, 2, 3, 4, 5 4} 5 6restParams(1, 2, 3, 4, 5)
使用...将数组展开
1const arr = [1, 2, 3] 2 3console.log(...arr) 4// 等价于es5中以下写法 5console.log.apply(console, arr)
特性&优势:
1const inc = (n) => n + 1 2console.log(inc(100)) 3 4const obj = { 5 name: 'aa', 6 func() { 7 setTimeout(() => { 8 console.log(this.name) //aa 9 }, 0) 10 setTimeout(function () { 11 console.log(this.name) //undefined 12 }, 0) 13 }, 14} 15obj.func()
1/** 2 * 1、增强了对象字面量: 3 * 1,同名属性可以省略key:value形式,直接key, 4 * 2,函数可以省略key:value形式 5 * 3,可以直接func(), 6 * 4,可以使用计算属性,比如:{[Math.random()]: value} 7 */ 8const arr = [1, 2, 3] 9const obj = { 10 arr, 11 func() { 12 console.log(this.arr) 13 }, 14 [Math.random()]: arr, 15} 16 17console.log(obj)
1/** 2 * Object.assign(target1, target2, ...targetn) 3 * 后面的属性向前面的属性合并 4 * 如果target1是空对象,可以创建一个全新对象,而不是对象引用 5 */ 6const obj1 = { 7 a: 1, 8 b: 2, 9} 10const obj2 = { 11 a: 1, 12 b: 2, 13} 14 15const obj3 = Object.assign({}, obj1) 16obj3.a = 5 17console.log(obj3, obj2, obj1)
作用:比较两个值是否相等
特性:
1console.log(NaN === NaN) //false 2console.log(Object.is(NaN, NaN)) //true 3console.log(0 === -0) // true 4console.log(Object.is(0, -0)) //false 5console.log(Object.is(1, 1)) //true
作用:
用法:
1const P = { 2 n: 'p', 3 a: 19, 4} 5 6const proxy = new Proxy(P, { 7 get(target, property) { 8 console.log(target, property) 9 return property in target ? target[property] : null 10 }, 11 defineProperty(target, property, attrs) { 12 console.log(target, property, attrs) 13 // throw new Error('不允许修改') 14 }, 15 deleteProperty(target, property) { 16 console.log(target, property) 17 delete target[property] 18 }, 19 set(target, property, value) { 20 target[property] = value 21 }, 22}) 23 24proxy.c = 100 25console.log('pp', P)
与 Object.definePropert 对比
优势:
作用:
集成 Object 操作的所有方法,统一、方便,具体方法如下:
用于对对象的统一操作,集成 Object 相关的所有方法
1、apply:类似 Function.prototype.apply
2、Reflect.construct()
对构造函数进行 new 操作,相当于执行 new target(...args)。
3、Reflect.defineProperty()
和 Object.defineProperty() 类似。
4、Reflect.deleteProperty()
作为函数的 delete 操作符,相当于执行 delete target[name]。
5、Reflect.get()
获取对象身上某个属性的值,类似于 target[name]。
6、Reflect.getOwnPropertyDescriptor()
类似于 Object.getOwnPropertyDescriptor()。
7、Reflect.getPrototypeOf()
类似于 Object.getPrototypeOf(), 获取目标对象的原型。
8、Reflect.has()
判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
9、Reflect.isExtensible()
类似于 Object.isExtensible().判断对象是否可扩展,可以添加额外属性
Object.seal(封闭对象), Object.freeze(冻结对象)是不可扩展的
10、Reflect.ownKeys()
返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受 enumerable 影响).
11、Reflect.preventExtensions()
类似于 Object.preventExtensions()。返回一个 Boolean。
12、Reflect.set()
将值分配给属性的函数。返回一个 Boolean,如果更新成功,则返回 true, 反之返回 false。
13、Reflect.setPrototypeOf()
类似于 Object.setPrototypeOf()。
示例:
1const obj = { 2 name: 'reflect', 3} 4Reflect.preventExtensions(obj) //禁止扩展 5console.log(Reflect.set(obj, 'age', 'xiaobai')) //false 6console.log(obj) //{ name: 'reflect' } 7console.log(Reflect.isExtensible(obj, 'name')) //false 8console.log(Reflect.ownKeys(obj)) //[ 'name' ]
作用:解决异步编程中回调嵌套过深问题
定义
1class Person { 2 constructor(props) { 3 this.props = props 4 } 5}
方法
1class Person { 2 constructor(props) { 3 this.props = props 4 } 5 // 实例方法 6 eat() {} 7 // 静态方法 8 static run() {} 9} 10// 调用静态方法 11Person.run() 12const person = new Person('props') 13// 调用实例方法 14person.eat()
继承:子类使用 extends 关键字实现继承,可以继承父类所有属性
1class Student extends Person { 2 constructor(props) { 3 super(props) 4 } 5 printProps() { 6 console.log(this.props) 7 } 8} 9 10const student = new Student('student') 11student.printProps()
说明:
Set 是一种类似于数组的数据结构
特性:
用途:
1const arr = [1, 3, 1, 1, 1] 2const set = new Set(arr) 3set.add(1).add(1) 4console.log(set.size) //2 5const newArr = Array.from(set) 6console.log(newArr) //[ 1, 3 ]
说明:
类似 Object,以 key、value 形式存储数据
区别:
Map 键不会隐式转换成字符串,而是保持原有类型
实例:
1const map = new Map() 2map.set(1, 1) 3map.set('name', 'map') 4map.set(obj, obj) 5console.log(map.get(1)) //1 6/** 7 1 1 8 name map 9 { '1': 1, true: true, a: 'a' } { '1': 1, true: true, a: 'a' } 10 */ 11map.forEach((val, key) => { 12 console.log(key, val) 13})
说明:
JavaScript 第六种原始数据类型,用来定义一个唯一的变量
作用:
创建唯一的变量,解决对象键名重复问题
为对象、类、函数等创建私有属性
修改对象的 toString 标签
为对象添加迭代器属性
如何获取对象的 symbol 属性?
实例
1// 对象属性重名问题; 2const objSymbol = { 3 [Symbol()]: 1, 4 [Symbol()]: 2, 5} 6console.log(objSymbol) 7 8// 2、为对象、类、函数等创建私有属性 9const name = Symbol() 10const obj2 = { 11 [name]: 'symbol', 12 testPrivate() { 13 console.log(this[name]) 14 }, 15} 16 17obj2.testPrivate() 18// 定义toString标签; 19console.log(obj2.toString()) 20obj2[Symbol.toStringTag] = 'xx' 21console.log(obj2.toString()) //[object xx]
用途:
已统一的方式,遍历所有引用数据类型
特性:
可以随时使用 break 终止遍历,而 forEach 不行
实例:
1// 基本用法 2// 遍历数组 3const arr = [1, 2, 3, 4] 4for (const item of arr) { 5 if (item > 3) { 6 break 7 } 8 if (item > 2) { 9 console.log(item) 10 } 11} 12 13// 遍历set 14const set = new Set() 15set.add('foo').add('bar') 16for (const item of set) { 17 console.log('set for of', item) 18} 19// 遍历map 20const map = new Map() 21map.set('foo', 'one').set('bar', 'two') 22for (const [key, val] of map) { 23 console.log('for of map', key, val) 24} 25//迭代对象 26const obj = { 27 name: 'xiaohui', 28 age: '10', 29 store: [1, 2, 3], 30 // 实现可迭代的接口 31 [Symbol.iterator]: function () { 32 const params = [this.name, this.age, this.store] 33 let index = 0 34 return { 35 next() { 36 const ret = { 37 value: params[index], 38 done: index >= params.length, 39 } 40 index++ 41 return ret 42 }, 43 } 44 }, 45} 46 47for (const item of obj) { 48 console.log('obj for of', item) 49}
作用:通过 Symbol.interator 对外提供统一的接口,获取内部的数据
外部可以通过 for...of...去迭代内部的数据
1const tods = { 2 life: ['eat', 'sleep'], 3 learn: ['js', 'dart'], 4 // 增加的任务 5 work: ['sale', 'customer'], 6 [Symbol.iterator]: function () { 7 const all = [] 8 Object.keys(this).forEach((key) => { 9 all.push(...this[key]) 10 }) 11 let index = 0 12 return { 13 next() { 14 const ret = { 15 value: all[index], 16 done: index >= all.length, 17 } 18 index++ 19 return ret 20 }, 21 } 22 }, 23} 24 25for (const item of tods) { 26 console.log(item) 27}
1// 生成迭代器方法 2// 生成器Generator的应用 3 4function* createIdGenerator() { 5 let id = 1 6 while (id < 3) yield id++ 7} 8const createId = createIdGenerator() 9console.log(createId.next()) //{ value: 1, done: false } 10console.log(createId.next()) //{ value: 2, done: false } 11console.log(createId.next()) //{ value: undefined, done: true } 12 13const todos = { 14 life: ['eat', 'sleep', 'baba'], 15 learn: ['es5', 'es6', 'design pattern'], 16 work: ['b', 'c', 'framework'], 17 [Symbol.iterator]: function* () { 18 const all = [...this.life, ...this.learn, ...this.work] 19 for (const i of all) { 20 yield i 21 } 22 }, 23} 24for (const item of todos) { 25 console.log(item) 26}
判断数组是否包含某个元素,包含 NaN,解决 indexOf 无法查找 NaN 问题
1// includes函数 2const arr = ['foo', 'bar', 'baz', NaN] 3console.log(arr.includes(NaN)) //true 4console.log(arr.indexOf(NaN)) //-1
指数运算
1// 指数运算符 ** 2// es5中2十次方 3console.log(Math.pow(2, 10)) 4// es6中2十次方 5console.log(2 ** 10)
将对象的值以数组的形式返回
1const obj = { 2 foo: 1, 3 bar: 2, 4 baz: 3, 5} 6 7console.log(Object.values(obj)) //[ 1, 2, 3 ]
将对象以键值对二维数组返回,使之可以使用 for...of...遍历
1const obj = { 2 foo: 1, 3 bar: 2, 4 baz: 3, 5} 6console.log(Object.entries(obj)) 7const entry = Object.entries(obj) 8for (const [key, value] of entry) { 9 console.log(key, value) 10}
获取对象的描述信息
可以通过获得的描述信息,配合 Object.defineProperties 来完整复制对象,包含 get,set 方法
1// getOwnPropertyDescriptors 2 3// 普通get方法 4const objGet = { 5 foo: 1, 6 bar: 2, 7 get getCount() { 8 return this.foo + this.bar 9 }, 10} 11// assign方法会把getCount当做普通属性复制,从而getCount为3,修改bar不管用 12const objGet1 = Object.assign({}, objGet) 13objGet1.bar = 3 14console.log(objGet1.getCount) //3 15// descriptors 16const descriptors = Object.getOwnPropertyDescriptors(objGet) 17console.log('des', descriptors) 18// 通过descriptors来复制对象,可以完整复制对象,包含get,set 19const objGet2 = Object.defineProperties({}, descriptors) 20objGet2.bar = 3 21console.log(objGet2.getCount) //4
在字符串前,或者后面追加指定字符串
参数:
targetLenght: 填充后的目标长度
padString:填充的字符串
规则:
1、填充的字符串超过目标长度,会在规定长度时被截断
2、填充字符串太短会以空格填充
3、padString 未传值,以空格填充
作用:
一般用来对齐字符串输出
1 2 /** 3 * foo.................|1 4 barbar..............|2 5 bazbazbaz...........|3 6 */ 7 console.log(`${key.padEnd(20, '.')}${value.toString().padStart(2, '|')}`)
最近更新时间:2024-08-10