问题导向
es2015,es6+
如果你都有了答案,可以忽略本文章,或去JS学习地图寻找更多答案
var let const
一般使用let 和 const
需要重新赋值 ? 使用let : 使用const
箭头函数
函数的简写
没有参数,没有返回值
let fn = () => console.log('hello arrow function')
有参数,有返回值,return可不写,=>后面是返回值
let fn = (num) => num
console.log(fn(5)) // 5
例子:补0操作,一个参数的话,()可省
let fn = num => num < 10 ? '0' + num : num
console.log(fn(5)) // 05
多个参数,多个返回值
let fn = (arg1, arg2) => arg1 + arg2
console.log(fn(5,6)) // 11
如果返回是一个对象,加()
let fn = () => ( {name:'li'} )
有多行执行语句,加{}
let fn = () => {
let a = 5;
let b = 4;
return a + b
}
模板字符串
使用反引号``,可随意换行
let fn = () => `
<div>
<p>666</p>
</div>
`
console.log(fn()) //<div><p>666</p></div>
插值表达式${表达式},和模板字符串配合使用
let str = `你好,我是${false ? '大哥': '爸爸'}`
console.log(str) //你好,我是爸爸
插入数组
let arr = ['苹果','香蕉']
let str = `我爱吃${arr[0],arr[1]}`
console.log(str) //我爱吃香蕉,这样只能插入1条数据,默认插入最后一个
let str2 = `我爱吃${arr}`
console.log(str2) //插入多条,我爱吃苹果,香蕉
插入函数
let fn = () => '苹果'
let str = `我爱吃${fn()}`
console.log(str) //我爱吃苹果
动态属性计算
// 写死
let p = {
name: '李四',
age: 20
}
// 动态属性计算:根据attName设置,相当于占位符
let fn = () => Math.random() > 0.5 ? 'name' : 'nickname'
let attName = fn()
let p = {
[attName]: '李四',
age: 20
}
Symbol
定义:一种新的原始数据类型,表示独一无二的值
作用:保护特殊的值
// 设置
let name = Symbol('name')
let age = Symbol('age')
let obj = {
[age]: 18,
[name]: 'tom',
sex: 'male'
}
// 读取Symbol属性
console.log(obj[name]) // tom
// 读取普通对象属性
console.log(obj['sex']) // male
// 覆盖
obj[age] = 20
// 无法获取Symbol的值,只获取到了普通对象的值male
for (let item in obj) {
console.log(obj[item])
}
// 获取Symbol的值
let result = Object.getOwnPropertySymbols(obj)
for (let item in result) {
console.log(obj[result[item]])
}
// 使用
let user = {
name: '李四',
learning: Symbol()
}
let grade = {
[user.learning]: { js: 80 },
}
console.log(grade[user.learning]) //{js: 100}
Set
定义:数据结构,是对象,也是容器,类似数组,成员的值是唯一的,常用于去重,查找交集,差集
属性和方法
属性:
size:长度,相当于length
方法:
add增加
has是否存在
delete删除
clear清除
keys键集合
values值集合
entries键值对集合
使用例子:
//添加:不会添加重复的值
let set = new Set()
set.add(1)
set.add(1) // 第二次不会成功
//判断是否存在,返回布尔值
set.has(1) // true
//删除set中的数组
set.forEach(n => n instanceof Array && set.delete(n))
//转成数组
1. Array.from(set)
2. [...set]
//查找并集,交集,差集
let a = new Set([1,2,3,4])
let b = new Set([1,6,3,8])
//并集:没有重复,就是去重,返回不是数组,使用Array.from转成数组
Array.from(new Set([...a,...b])) //1,2,3,4,6,8
//查找a中b的差集:b没有的
new Set([...a].filter(item => !b.has(item))) //2,4
//交集:共有的
new Set([...a].filter(item => b.has(item))) //1,3
Map
定义:数据结构,键值对的集合
与set不同的是,map传入的是键值对,可以是任意类型的值,如:dom节点
属性和方法
属性:
size:长度,相当于length
方法:
set增加
get获取值
has是否存在
delete删除
clear清除
keys键集合
values值集合
entries键值对集合
使用例子
// 添加
let map = new Map()
map.set('name','tom')
// 长度
map.size // 1
// 获取
map.get('name') // tom
// 判断
map.has('name') // true
// 删除
map.delete('name') // true
// 清空
map.clear()
// 遍历获取建值对,for-of配合entries
for(let [k,v] of map.entries()){
console.log(k,v)
}
proxy
定义:代理拦截器,通过代理操作数据,有了代理拦截,相当于可以帮助我们重写对象属性和方法的默认操作
如:买主 - 中介 - 卖主
// 语法
let proxy = new Proxy(target, handler)
target:参数表示拦截的目标对象(代理谁)
handler:参数也是一个对象,用来定制拦截行为(行为)
// 拦截行为
get(target, Key, receiver):拦截对象属性的读取,3个参数:目标,key值,proxy对象
set(target, Key, value, receiver):拦截对象属性的设置
has(target, Key):拦截propKey in proxy的操作,返回一个布尔值
deleteProperty(target, propKey):拦截deleteProperty[propKey]的操作,返回一个布尔值
// 例子1:使用代理读写对象,如果读的属性不存在,就抛出错误
let obj = { name: 'tao' }
let objProxy = new Proxy(obj, {
get(obj, key) {
if (key in obj) {
return obj[key]
} else {
throw new ReferenceError(`该对象不存在${key}属性`)
}
},
set(obj, key, value) {
obj[key] = value
},
})
// 使用代理调用,而不是使用obj调用
console.log(objProxy.name) //访问触发get,获取返回值
objProxy.name = 'tom' //赋值触发set,重写name属性
console.log(objProxy.name) //tom
console.log(objProxy.age) //age属性不存在,抛出自定义的错误错误
// 遍历
Object.keys(objProxy).forEach(k => console.log(objProxy[k]))
// 例子2:以 '188****5555' 格式读取手机号码
let arr = [{ phone: 13866668888 }, { phone: 18833335555 }]
let proxy = new Proxy(arr, {
get(arr, key) {
let p = String(arr[key].phone)
arr[key].phone = p.replace(p.slice(3, 7), '****')
return arr[key]
},
})
console.log(arr[1]) //数组读取:{phone: 18833335555}
console.log(proxy[1]) //代理读取:{phone: '188****5555'}
合并空运算符
let obj = {
name: 'tom'
}
console.log(a.age || 10) //10,前面为真 ? 输出前面 :输出后面
console.log(a.age ?? 10) //10,前面为真 ? 输出前面 :输出后面
console.log(a.age && 10) //undefined,短路逻辑,前面为真才执行
可选链
下面例子,如果不加?,会报无法读取undefined属性的错误,加了?,就读age,如果age不存在,不会报错,执行后面的逻辑
let obj = {
name: 'tom'
}
console.log(a.age?.max ?? 88) //88
私有变量
class P {
#name = 'hello' //私有属性,相当于ts中private
age = 18 //共有属性
get() {
console.log(this.#name)
}
}
const p = new P()
console.log(p.age) //可读,非私有属性
console.log(p.#name) //报错,私有属性
p.get() //可以通过getter读取
学习更多