? ? 本课程主要是针对ECMAScript新特性的罗列以及代码。加强对ECMAScript的运用以及更深了解。
块级作用域
let? 关键字
1.块级作用域
//因为之前的没用块级作用域,所以,i只打印3次 0,1,2
for(var i=0;i<3;i++){
for(var i=0;i<3;i++){
console.log(i)
}
}
//有了块级作用域,可以打印9次, 0,1,2 0,1,2 0,1,2
for(let i=0;i<3;i++){
for(let i=0;i<3;i++){
console.log(i)
}
}
2.不会产生变量提升
必须先声明,在使用。
console.log(a); //undefined
var a="hello"
console.log(b); //Cannot access 'b' before initialization
let b = "hello"
const? 关键字
常量,不能修改,也是块级作用域,等同于let的块级作用域。
//基本数据声明之后,就不能修改。
const name = "hello"
name = "123" //Assignment to constant variable.
//但是可以为声明的对象,添加属性。因为引用属性,是指向堆内存的地址,
//添加属性,只是在这个地址指向的堆内存追加属性,没有改变地址的指向。
const obj = {}
obj.name="123"
数组、对象的解构,模板字符串
数组解构
//[]里边用设置为空逗号分隔,然后获取的哪一项,声明一个名字。就可以获得对应索引的数组元素。
const arr = [100,200,300]
const [,,dir] = arr
console.log(dir) // 300
// 1、...的数组解构只能放到最后一项,或者在没有其对应索引值的情况下,可以直接获取数组全部元素
const [foo,...rest] = arr
console.log(rest) // [200,300]
//2、当解构成员个数小于数组成员个数,那么从前到后,解构
const [foo] = arr
console.log(foo) //100
//3、当解构的成员个数大于数组成员个数,那么会报出undefined
const [foo,bar,str,more] = arr
console.log(more) //undefined
//或者可以给多出来的成员,默认赋值
const [foo,bar,str,more="123"] = arr
console.log(more) //123
对象解构
// 对象解构,解构的名称必须于对象的名称相对应
const obj = {name:'ht',age:18}
const {name} = obj;
console.log(name) //ht
// 如果有一个已经声明的name 变量了,就会引起冲突。
const name = "zce"
const {name} = obj;
console.log(name) //Identifier 'name' has already been declared
//为了解决这个命名冲突,我们可以给解构变量name后边跟一个 自定义名称
const name = "zce"
const {name : objName} = obj;
console.log(objName) // ht
模板字符串
//区别于之前的""、''的字符串声明,es6 添加了模板字符串``,支持换行,
const str = `hello
world`
console.log(str) 输出换行的hello world
//支持插值表达式,可以输入任何的标准的语句
const name = "ht"
const msg = `hey,${name}`
console.log(msg ) //hey,ht
console.log(`hey,${1+2}`) //hey,3
带标签的模板字符串
const str = console.log `hello world` //输出[ 'hello world' ]
const name = 'Ht'
const genter = true
function myTagFun(str,name,genter){
console.log(str,name,genter)
//打印出来的是[ 'hey,', ' is a ', '.' ] 分割后的静态的没有插值表达式的一个数组
}
const result = myTagFun`hey,${name} is a ${genter}.`
//要把所有的插值表达式传入进去,才可以拿到全部的数据
const name = 'Ht'
const genter = true
function myTagFun(str,name,genter){
//return 123
return str[0]+name+str[1]+genter+str[2]
}
const result = myTagFun`hey,${name} is a ${genter}.` //这个就是myTagFun的返回值
console.log(result) //hey,Ht is a true.
//标签模板字符串,可以对模板字符串进行加工
const name = 'Ht'
const genter = true
function myTagFun(str,name,genter){
const sex = genter ? "man" : "woman"
return str[0]+name+str[1]+genter+str[2]
}
const result = myTagFun`hey,${name} is a ${genter}.`
console.log(result) //hey,Ht is a man.
字符串扩展方法
includes()、startsWith()、endsWith()? ?//判断字符串中是否包含指定的内容
const msg = "Hi,Ht hello world"
//startsWith判断字符串是某个字符开头
console.log(msg.startsWith("Hi")) //true 的
//endsWith判断字符串是某个字符结尾的
console.log(msg.endsWith("world")) //true
//includes判断字符串是包含某个字符
console.log(msg.includes("Ht")) //true
函数新特性
参数默认值
function foo(enable = true){
console.log(enable)
}
//没有实参或者实参为undefined时候可以使用,别切带有默认参数的参数必须放到最后
foo() //true
foo(false) //false
剩余参数? ...
1、剩余参数
function foo(num,...args){
console.log(args)
}
//输出一个数组,从当前num位置往后的所有剩余参数,都会被打印出来
foo(1,2,3,4) //[2,3,4]
2、展开数组
const arr = ['foo','bar', 'baz']
console.log(...arr)
箭头函数? ?=>?
// function inc(number){
// return number++
// }
//箭头定义的函数等同于上边的定以普通函数 在没有大括号的单条语句情况下,
//const inc = n=>n++
//箭头函数默认把=>后边的值作为返回值。
// 多条语句的情况下 必须需要手动返回
const inc = (n,m) =>{
return n++
}
console.log(inc(1))
并且,箭头函数没有this和arguments
对象
对象字面量
const age = '18'
const obj = {
name:'Ht',
// age:age
age, //等同于上边的age:age
// foo:function(){
// console.log("111")
// console.log(this)
// },
foo(){
console.log("111")
console.log(this)
},
//计算属性名
//[Math.random()]:'123'
[age]:"123" //{ '18': '123', name: 'Ht', age: '18', foo: [Function: foo] }
}
console.log(obj)
obj.foo()
// [Math.random()]:'123' 输出
// {
// name: 'Ht',
// age: '18',
// foo: [Function: foo],
// '0.5655320116314375': '123'
// }
对象扩展方法
1、Object.assign? ?//将多个源对象的属性复制到一个目标对象中,如果属性名称重复,源对象的属性,会覆盖目标对象的属性。可以复制出来一个全新的对象,从而不会原来对象做修改
const obj1 = {
a:123,
b:123,
}
const obj2 = {
a:456,
c:456
}
const result = Object.assign(obj2,obj1)
console.log(obj2) //{ a: 123, c: 456, b: 123 }
console.log(result === obj2) //true
const obj1 = {
a:123,
b:123,
}
const obj3 = {
b:789,
d:789
}
const obj2 = {
a:456,
c:456
}
const result = Object.assign(obj2,obj1)
console.log(obj2) //{ a: 123, c: 456, b: 789, d: 789 }
//总结:就是后边参数中的对象属性,会覆盖第一个对象属性中重名的那个
2、Object.is方法? 判断两个值是否相等。
// == 存在隐式转换数据类型的隐患,所以用 ===
// 但是 === 没去区分 +0===-0 //true NaN ===NaN //false
console.log(-0 === +0) //true
console.log(NaN === NaN) //false
console.log(Object.is(NaN,NaN)) //true
console.log(Object.is(-0,+0)) //false
Proxy?
代理对象
ES5中的Object.defineProperty这样的方法可以捕获对象中的属性的读写过程。Vue3之前的双向数据绑定就是基于这个实现。ES2015中新增了 Proxy。
//Proxy() 第一个参数,代理的对象
const person = {
name:"Ht",
age:18
}
const personProxy = new Proxy(person,{
get(target,property){
// console.log(target,property)
// return 100
return property in target ?target[property] :"default"
},
set(target,property,value){
// console.log(target,property,value)
if(property ==="age"){
if(!Number.isInteger(value)){
throw new TypeError(`${value} is not an int`)
}
}
target[property] = value
}
})
personProxy.genter = "hahah"
personProxy.age = 123
console.log(personProxy.name)
console.log(personProxy.xxx)
Object.defineProperty与Proxy比较
Object.defineProperty:只监视属性的读写。
Proxy:能监视更多的对象操作,删除,对象方法的调用
const person = {
name:"Ht",
age:18
}
const personProxy = new Proxy(person,{
deleteProperty(target,propperty){
console.log("delete",propperty)
delete target[propperty]
}
})
delete personProxy.age;
console.log(person)
Reflect?
统一的对象操作API,内部封装了一系列对象的底层操作。就是Proxy处理对象的默认实现。
const obj = {
name: 'Ht',
age: 18
}
console.log(Reflect.has(obj, "name"))
console.log(Reflect.deleteProperty(obj, "age"))
console.log(Reflect.ownKeys(obj))
Promise
异步编程 :
class 类
具体实现
function Person(name) {
this.name = name
}
Person.prototype.say = function() {
console.log(`hi,my name is ${this.name}`)
}
class Preson {
constructor(name) {
this.name = name
}
say() {
console.log(`hi,my name is ${this.name}`)
}
}
const p = new Preson("tom")
p.say()
实例方法 VS 静态方法
静态方法的关键词:static
function Person(name) {
this.name = name
}
Person.prototype.say = function() {
console.log(`hi,my name is ${this.name}`)
}
class Person {
constructor(name) {
this.name = name
}
say() {
console.log(`hi,my name is ${this.name}`)
}
static create(name) {
// console.log(name)
return new Preson(name)
}
}
const p = new Preson("tom")
p.say()
类的继承?
关键字:extends
class Person {
constructor(name) {
this.name = name
}
say() {
console.log(`hi,my name is ${this.name}`)
}
}
class Student extends Person {
constructor(name, number) {
super(name)
this.number = number
}
hello() {
super.say()
console.log(`my school number is ${this.number}`)
}
}
const p = new Student("tom", '100')
p.hello()
//hi,my name is tom
//my school number is 100
Set 数据结构
每一个值都是唯一的,不允许重复。
const s = new Set();
s.add(1).add(2).add(1).add(3)
console.log(s) //Set(3) { 1, 2, 3 }
s.forEach(i => console.log(i)) //1 2 3
for (let i of s) {
console.log(i) //等同于上边的forEach 方法 1 2 3
}
console.log(s.size) //3 等同于 数组的length
console.log(s.has(4)) //判断s中是否存在元素4 false
console.log(s.delete(2)) //true
s.clear()
console.log(s) //清除s中的所有元素 Set {}
Map数据结构
任意数据作为键,对象只能用字符串作为键
const m = new Map()
const tom = { name: "tom" }
m.set(tom, 90)
console.log(m) //Map(1) { { name: 'tom' } => 90 }
console.log(m.get(tom)) // 90
//m.has()
//m.delete()
//m.clear()
Symbol??
全新的原始数据类型—>独一无二的值,可以作为对象的键? ?添加独一无二的属性名
console.log(Symbol("foo") === Symbol("foo")) // false
console.log(Symbol.for("foo") === Symbol.for("foo")) //true
Iterable?
迭代器
const obj = {
store: ['foo', 'bar', 'baz'],
[Symbol.iterator]: function() {
let index = 0
const self = this
return {
next: function() {
const result = {
value: self.store[index],
done: index >= self.store.length
}
index++
return result
}
}
}
}
for (const item of obj) {
console.log("循环体", item) //循环体 foo 循环体 bar 循环体 baz
}
Generator
在普通函数名前边加一个*? ?
function * foo() {
console.log('zce')
return 100
}
const result = foo()
console.log(result.next())
必须配合yield的关键字
function* foo() {
console.log('1111')
yield 100
console.log('2222')
yield 200
console.log('333')
yield 300
}
const g = foo()
//yield 惰性执行,调去一次才去执行一次,
//一直到foo函数里边没有了yield的返回值,最后是value undefined
console.log(g.next()) // 1111 { value: 100, done: false }
console.log(g.next()) // 2222{ value: 200, done: false }
console.log(g.next()) // 333{ value: 300, done: false }
console.log(g.next()) //{ value: undefined, done: true }
实现发号器
function* createIdMaker() {
let id = 1
while (true) {
yield id++
}
}
const IdMaker = createIdMaker()
console.log(IdMaker.next().value)
console.log(IdMaker.next().value)
console.log(IdMaker.next().value)
console.log(IdMaker.next().value)
//打印 1 2 3 4
ES2016
1、数组的 includes方法
const arr = [1, 2, 3, 4]
console.log(arr.includes(1))
2、指数运算符
console.log(Math.pow(2, 10)) //1024
console.log(2 ** 10) //1024
ES2017
1、Object.values()
const obj = {
foo: 'value',
bar: 'value2'
}
console.log(Object.values(obj)) // [ 'value', 'value2' ] 所有值反悔的数组
2、Object.entries()
const?obj?=?{
????foo:?'value',
????bar:?'value2'
}
//以数组的形式,返回对象的键值对
console.log(Object.entries(obj)) //[ [ 'foo', 'value' ], [ 'bar', 'value2' ] ]
3、Object.getOwnPropertyDescriptors? 配合get set使用
4、String.prototype.padStart /?String.prototype.padEnd
通过制定字符填充制定字符串结尾或者开始位置,直到达到指定长度位置
5、函数参数中添加尾逗号
function foo(
bar,baz,
){}
6、Async/Await? ?promise的语法糖
|