加油,夏慧敏,热爱生活
一、var、let、const
早期 es6之前
每个执行上下文都会被关联到一个变量环境中Vo, 在源代码中的变量和函数的声明也会被当作属性添加到Vo中,对于函数来说,参数也会被Vo中
es6之后
每个执行上下文会被关联到一个变量环境中,在执行代码中变量和函数的声明会被作为环境记录添加到变量环境中,对于函数来说,参数也会被作为环境记录添加到变量环境中
- v8 中其实是通过 variableMap 的hashmap 来实现他们存储的
- 早期的时候window对象就是早期的Go,.所以var声明的变量是浏览器的全局对象
重复定义 | 定义变量的作用域 | 作用域提升 | 暂时性死区 | ||
---|---|---|---|---|---|
var | 可以 | 函数作用域 | 可以 | 无 | 全局作用域时会成为window属性 |
let | 不可以 | 块级作用域 | 不可以 | 有 | |
const | 不可以 | 块级作用域 | 不可以 | 有 |
- 暂时性死区:使用let const 在声明之前是不可以使用的
- var 有一些特殊性,比如作用域提升,window全局对象,没有块级作用域等都是历史遗留问题,所以尽可能用const和let代替var
二、作用域
- es6 之前 只有 var,所以只有全局作用域和函数作用域
- es6 之后 添加了let 和 const ,所以又有了 块级作用域 { }
if(){
块级作用域
}
for(){
块级作用域
}
三、函数周边知识
函数的参数默认值:
ES6 之前, 当传入的值为 false, 0 ,'' ...会产生bug
function foo(m,n){
m = m || 'aaa'
n = n || 'bbb'
}
foo('',false) // 程序里就会赋后面的值
ES6 之后
function foo(m='aaa',n='bbb'){
}
对象参数的默认值和解构:
方法一
function foo({name,age}={name:'why,age:18}){
console.log(name,age)
}
方法二
function foo({name='why',age=18}={}){
console.log(name,age)
}
函数的剩余参数:
function foo(m,n,...agrs){
console.log(m,n)
conosle.log(agrs)
}
foo(20,30,20,5,30)
- 如果最后一个参数以…为前缀,将会把接收的剩余参数放到一个数组里
剩余参数和arguments的区别
- arguments 只是早期ecma 官方方便开发者获取所有函数参数的一个数据结构,所以argument获取的是所有的参数,且并不是一个真正的数组
- 剩余参数是一个真正的参数,可以进行数组的所有操作,剩余参数是指那些没有对应形参的实参
箭头函数:
- 箭头函数因为没有显式原型,所以不能使用new构建对象
- 箭头函数没有this , 他的this 指向他父级的执行上下文
- 箭头函数没有arguments
四、展开语法
- 在函数调用时使用
const names = ["abc","cba" ,"nba"]
const name = "why"2
function foo(x,y, z) {
console.log(x,y,z)
}
foo(...names) = foo("abc","cba" ,"nba")
foo(...name) = foo('w','h','y')
- 构造数组时
const newNames = [...names, ...name] // 看下面的总结
console.Log(newNames)
- 在函数调用/数组构造时,将数组表达式或者string在语法层面展开
- 在构造字面量对象时 , 将对象表达式按key-value的方式展开;
- es6 语法
const newNames ={...name , age:18}
- 展开运算符是浅拷贝
五、数值表示
let m= 8 // 默认情况下是十进制,
let n=0b100 // 二进制
let n2=0o100 // 八进制
let n3=0x100 // 十六进制
symbol
- es6 新增的一种基本类型,翻译为符号
- 在es6之前,对象的属性key内部其实都是字符串形式进行保存,假设我们要对某个对象添加新的属性和值,在不确定他原来内部都有什么内容的情况下,很容易照成冲突,从而覆盖掉他内部的某个属性,比如开发我们使用混入时,出现同名属性必然有个就会被覆盖掉
- es6之后,对象的属性值可以使用字符串,也可以使用symbol
const s1= Symbol() // 其实symbol 是个函数
const s2= Symbol()
console.log(s1,s2) //false
1. 定义属性时使用
const obj={
[s1]:'abc'
[s2]:'bac'
}
2.新增属性时使用
obj[s2]='nab'
获取:
console.log(obj[s1],obj[s2]) //不能以点语法形式获取
- 使用symbol作为key的属性名,遍历object.keys等中是获取不到的
const sKeys = Object.getOwnPropertySymbols(obj) // 先获取所有symbol 的key
for (const item of obj[sKeys]){
}
六、set 的使用
- 在ES6之前,我们存储数据的结构主要有两种:数组、对象。 在ES6中新增了另外两种数据结构:Set、Map
- Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。
- 创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式):
const set = new Set()
set.add(10)
set.add(20)
set.add(10)
console.log(set) // 10,20 因为set存放的元素不会重复
const set2 = new Set()
set2.add({})
set2.add({})
console.log(set) // {},{} 因为set 存放的是两个地址
const obj={}
set2.add(obj)
set2.add(obj)
console.log(set) // {} 因为存放的是一个地址
- 我们可以发现Set中存放的元素是不会重复的,那么Set有一个非常常用的功能就是给数组去重。
const arr=[1,2,3,4,5,1,2,3]
const arrSet = new Set(arr) // 通过 set 去重
console.log(arrSet) // 但是这里拿到的是set结构,我们需要array类型
const arrNew=Array.from(arrSet) // 方式一
const arrNew2=[...arrSet] // 方式二
console.log(arrNew,arrNew2)
常见的属性和方法:
console.log(arrNew.size) // 长度4
arrSet.add(10) // 添加
arrSet.delete(10) // 删除
arrSet.clear() // 清除
arrSet.has(10) // 是否包含
WeakSet使用:
-
和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构
-
那么和Set有什么区别呢?
- WeakSet中只能存放对象类型,不能存放基本数据类型;
- WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收;
-
WeakSet常见的方法
- . add(value):添加某个元素,返回WeakSet对象本身;
- delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
- has(value):判断WeakSet中是否存在某个元素,返回boolean类型;
七、map 的使用
- 另外一个新增的数据结构是Map,用于存储映射关系。
- 事实上我们对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key);
- 某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key;那么我们就可以使用Map
八、es7-12
Array.includes:
是否包含object.keys
和object.value
对于对象来说就是对象的属性和值,对于数组来说是索引和值,
const obj = {
name:'why'
age:18
}
console.log(object.keys) //['name','age']
const obj2 = [1,2,3]
console.log(object.keys) //['0','1','2']
const obj3 = '012'
console.log(object.value) //['0','1','2']
object.entries
获取对象可枚举的属性和值分别放入两个数组,返回一个数组是这个两个数组的集合
const obj = {
name:'why'
age:18
}
console.log(obj.entries(obj)) //[['name','age'],['why','18']]
Padding
字符串填充
const mes='hello world'
const newMes=mes.padStart(15,'*') // 如果不传第二个参数默认是空格
const newMes=mes.padEnd(15,'*')
-
flat
和flatMap
对数组进行降维 -
trim
和trimStart
和trimEnd
去空格 -
js 可表示的数字是有限的,超出可能运算不太准确,对于超出的数值可以在数值后面加n,如果运算数字也要加n表示,可以通过
bigInt
转化 -
??
空值运算符
const foo = undefined
const bar= foo || "default yalue" // 弊端: 对于''空字符串和0 和false会走默认值
const bar = foo ?? "defualt value" // 准确的 unde 和 null值
console.log(bar)
?.
空值选择器
let obj={
name:'xia',
friend:{
name:'wang'
}
}
console.log(obj.friend.name)
console.log(obj.friend2.name) // 阻止代码正常运行
//如果某个属性为null 或者 undefined ,就会提前阻止执行,
console.log(obj?.friend2.name) //避免null.XX或undefined.XX 造成后面代码产生问题
proxy
建议看下我的响应式原理
总结:
- 新增了 let 和 const 声明变量,因为let 和const定义变量作用域是块级作用域,新增了块级作用域
- 可以设置函数参数的默认值,及解构;
- 新增了剩余参数;新增了箭头函数;
- 新增了symbol;新增加了set和map 数据结构;
- 数组:includes ; 对象:object.keys , object.value , object.entries;
- 空值运算符 ;空值选择器;模板字符串
- proxy promise awiat async