目录
1.let const
// let 快级作用域
if (true) {
let a = '111'
}
console.log(a) // a is undefined
// const 无法修改内存地址的指向
const a = '111'
a = '222' // 无法修改
2.解构
// 数组解构
const arr = [1, 2, 3]
const [a, b , c] = arr
console.log(a, b, c) // 1 2 3
const [, , c]
console.log(c) // 3
const [a, ...b] = arr
conosle.log(arr) // [2, 3]
// 对象解构
const obj = { name: '11', age: 20 }
const { name } = obj
console.log(name ) // 11
// 变量名起冲突
const name = 'jon'
const { name: objName} = obj
console.log(obgName) // 11
3.模板字符串
const name = 'jon'
const alert = `hello, ${name} `
console.log(alert) // hello,jon
function a(a) {
console.log(a) // ['hello,'] ['is you']
}
function b(a, name) {
console.log(a, name) // ['hello,'] ['is you'] jon
}
const result = a`hello,${name} is you`
// 字符串扩展方法
includes() // 判断字符串
startsWith() // 判断字符串开头
endsWidth() // 判断字符串结尾
// 数组判断
const arr = [1, 3]
arr.includes('1') // true
// 指数运算符
const a = 2 ** 10 = Math.pow(2, 10)
4.箭头函数
// 使用箭头函数使代码更简单易读,且不会改变this的指向
const a = (a, b) => {
return a+b
}
// 字面量增强
const name = 'jon'
const obj1 = {
// 以前的方法,等同于下面的写法
name: name,
method1: function() {
console.log('111)
},
}
obj[Math.roadom()] = 123
const obj = {
name,
method1() {
console.log('111)
},
[Math.random()]: 123 // 计算属性名
}
5.Object.assign()
该方法可以将多个源对象属性复制到一个目标对象中
const obj1 = {
a: 123,
b: 234
}
const obj2 = {
a: 456,
c: 234
}
const result = Object.assign(obj1, obj2)
console.log(result) // { a:456, b:234, c:234 }
console.log(result === obj1) // true
第一个参数为目标对象,该方法返回值为目标对象。复制对象防止外部操作更改对象内容的时候可以复制空对象 Object.assign({}, obj1, ...)
6.Object.is
比较方法,判断2个值是否相等,区分与 === 和 == ,不建议使用
另外添加几种其余的新方法
0 == false // true
0 === false // false
NaN === NaN // false
Object.is(NaN, NaN) // true
const obj = {
name: 'jon',
age: 10
}
// Object.values
console.log(Object.values(obj)) // ['jon', 10]
// Object.entries
console.log(Object.entries(obj)) // [['name', 'jon'], ['age', 10]]
// 将对象转为map对象
new Map(Object.entries(obj))
// Object.getOwnPropertyDescriptors (配合get,set 属性使用)
const a1 = {
firstName: 'zhang',
lastName: 'san',
get fullName () {
return firstName + lastName
}
}
const descriptors = Object.getOwnPropertyDescriptors(a1)
const a2 = Object.defineProperties({}, descriptors)
p2.firstName = 'li'
console.log(p2.fullName) // li san
// string.propertype.padStart string.property.padEnd 用给定的字符串去填充目标字符串的开头和结束位置
const obj = {
name: 'jon',
age: 100
}
for (const [key, value] of Object.entries(obj)) {
console.log(`${name.padEnd(6, '-')}|${value.padStart(5, '0')}`)
// name--|00jon age---|00100
}
7.Proxy(代理过程)
Object.definedProperty 监视对象的属性的读写过程 (vue3.0之前数据双向绑定的核心方法(通过自定义的方式覆盖掉数组原型对象上的push等方法以此来劫持这个方法调用的过程)) es5
相对于definedProperty, Proxy使用更加简单且功能更加强大,例如(能监视到更多的对象操作,delete操作,方法调用等,能更好的监听数组对象,无需侵入),vue3.0中使用。
const peopel = {
name: 'jon',
age: 100
}
const peopleProxy = new Proxy(people, { // 入参为代理的目标对象,代理目标对象的处理对象
get(target, property) { // 入参为目标对象,属性名
return property in target? target[property ] : undefined
// 使用in方法查找,hasOwnProperty()方法无法从原型对象中查找
},
set(target, property, value) { // 入参为目标对象,属性名, 属性值
if (property === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('not int')
}
}
target[property] = value
}
})
const list = []
const listProxy = new Proxy(list,
set(target, property, value) {
console.log(property, value)
target[property] = value
return true // 设置成功
}
)
listProxy.push(10) // 1 10 length 1
8.Reflect(静态类)
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
9.promise(重点)异步编程链式调用
// 尽可能还原 Promise 中的每一个 API
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
class myPromise {
constructor (executor) {
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
status = PENDING
// 成功值
value = undefined
// 失败值
reason = undefined
// 异步存储方法
successCallBack = []
rejectCallBack = []
// 成功
resolve = value => {
// 判断状态
if (this.status !== PENDING) return
this.status = FULFILLED
// 传递值给then
this.value = value
// 判断回调是否存在
// this.successCallBack && this.successCallBack(value)
// 循环多个方法
while(this.successCallBack.length) {
this.successCallBack.shift()()
}
}
// 失败
reject = reason => {
// 判断状态
if (this.status !== PENDING) return
this.status = REJECTED
// 传递值给then
this.reason = reason
// 判断回调是否存在
// this.rejectCallBack && this.rejectCallBack(value)
// 循环多个方法
while(this.rejectCallBack.length) {
this.rejectCallBack.shift()()
}
}
// then原型对象上的方法 判断状态进行调用 有一个参数 返回的是promise对象
then (successCallBack, rejectCallBack) {
// 链式调用需要返回promise
successCallBack = successCallBack ? successCallBack : value => value
rejectCallBack = rejectCallBack ? rejectCallBack : reason => { throw reason }
let promiseTwo = new myPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 通过setTimeout切换成异步操作保证入参
setTimeout(() => {
try {
// 传递参数
let result = successCallBack(this.value)
resolvePromise(promiseTwo, result, resolve, reject)
} catch (e) {
reject(e)
}
}, 0);
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
// 传递参数
let resultTwo = rejectCallBack(this.reason)
resolvePromise(promiseTwo, resultTwo, resolve, reject)
} catch (e) {
reject(e)
}
}, 0);
} else {
// 异步操作的时候
// this.successCallBack.push(successCallBack)
// this.rejectCallBack.push(rejectCallBack)
// push回调函数没办法捕获处理 改为push有回调函数的函数
this.successCallBack.push(() => {
setTimeout(() => {
try {
let result = successCallBack(this.value)
resolvePromise(promiseTwo, result, resolve, reject)
} catch (e) {
reject(e)
}
}, 0);
})
this.rejectCallBack.push(() => {
setTimeout(() => {
try {
let resultTwo = rejectCallBack(this.reason)
resolvePromise(promiseTwo, resultTwo, resolve, reject)
} catch (e) {
reject(e)
}
}, 0);
})
}
})
return promiseTwo
}
finally (callback) {
this.then(value => {
return myPromise.resolve(callback()).then(() => value)
}, reason => {
return myPromise.resolve(callback()).then(() => { throw reason })
})
}
catch (callback) {
return this.then(undefined, callback)
}
// promise all方法
static all (Array) {
let resultArray = []
let index = 0
return new myPromise((resolve, reject) => {
// 数组添加
function addData(key, value) {
resultArray[key] = value
index++
if (index === Array.length) {
resolve(resultArray)
}
}
for (let i = 0; i< Array.length; i++) {
if (Array[i] instanceof myPromise) {
// promise对象
Array[i].then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, Array[i])
}
}
})
}
static resolve (value) {
// 判断是否是promise对象
if (value instanceof myPromise) {
return value
} else {
return new myPromise(resolve => resolve(value))
}
}
}
function resolvePromise(promiseTwo, result, resolve, reject) {
// 判断是否是自己返回了自己
if (promiseTwo === result) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
// 判断是否是promise对象
if (result instanceof myPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
}
module.exports = myPromise
10.class类
class people {
constructor(name) {
this.name = name
}
static showName(name) { // 静态方法是挂载到类型上面的,this指向当前类型,不指向实例
return new people(name)
}
sing () {
console.log('hello world')
}
}
console.log(new people('jon')) // jon
console.log(people.showName('jon')) // jon
extends 继承
class newPeople extends people {
constructor(name, age) {
super(name) // super继承
this.age = age
}
see () {
super.sing()
}
}
const a = new newPeople('jon', 100)
console.log(a.see) // hello world
11.set
const a = new Set()
a.add(1).add(2).add(1) // Set { 1, 2, 3 }
a.size // 3
a.has(1) // true
a.delete(1) //true
a.clear() // Set { }
// set 去重
const arr = [1, 2, 3, 1]
const array = Array.from(new Set(arr)) // [1, 2, 3]
12.Map
// Map可以用任意数值作为键
const a = new Map()
const name = { name: 'jon' }
a.set(name, 11)
console.log(a) // Map { { name: 'jon' } => 11 }
console.log(a.get(name)) // 11
//a.has() a.delete() a.clear()
a.forEach(value, key) => {
console.log(value, key) // 11 { name: 'jon' }
}
13.Symbol (为对象添加独一无二的属性名)
const a = Symbol('jon')
const b = Symbol('jon')
console.log(a === b) // false
// Symbol 可以作为属性名
const a = {}
const b = Symbol('jon')
a[b] = 11
// Symbol 值作为属性名时,该属性是公有属性不是私有属性,可以在类的外部访问。但是不会出现在 for...in 、 for...of 的循环中,也不会被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到
const a = Symbol.for('jon') // 非字符串会自动转化成字符串
Symbol.keyFor(a); // jon
const b = Symbol.for('jon')
console.log(a === b) // true
14.循环,迭代器,生成器
for of 循环能遍历所有符合iterable接口标准的数据结构(原型对象上都含有Symbol.iterator的方法)
// for...of
// 数组循环
const a = [1, 5, 10, 20]
// 迭代 工作原理
const iterator = a[Symbol.iterator]()
console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 5, done: false }
console.log(iterator.next()) // { value: 10, done: false }
console.log(iterator.next()) // { value: 20, done: false }
console.log(iterator.next()) // { value: undefined, done: true }
for (const item of a) {
console.log(item)
if (item > 5) {
break // 可跳出循环(适合所有数组伪数组Set Map)
}
}
// Map差异 键值对的循环
const m = new Map()
m.set('a', '1')
m.set('b', '2')
for (const item of m) {
console.log(item) // ['a', '1'] ['b', '2']
}
for (const [key, value] of m) {
console.log(key, value) // a 1 b 2
}
//将对象进行迭代
const obj = {
strings: ['a', 'b', 'c'],
more: ['d', 'e', 'f']
[Symbol.iterator]: function() {
let index = 0
const arr = [...this.strings, ...this.more]
return {
next: function() {
let result = {
value: arr[index]
done: index >= arr.length
}
index++
retrun result
}
}
}
}
// 生成器 generator (异步请求)
function * a () {
console.log('jon')
return 100
}
const result = a()
console.log(result.next()) // jon { value: 100, done: true}
function * a () {
console.log('1')
yield 100
console.log('2')
yield 200
console.log('3')
yield 300
}
const result = a()
console.log(result.next()) // 1 { value: 100, done: false}
console.log(result.next()) // 2 { value: 200, done: false}
console.log(result.next()) // 3 { value: 300, done: false}
console.log(result.next()) // { value: undefined, done: true}
// 使用生成器对迭代重组
const obj = {
strings: ['a', 'b', 'c'],
more: ['d', 'e', 'f']
[Symbol.iterator]: function *() {
const arr = [...this.strings, ...this.more]
for(const item of arr) {
yield item
}
}
}
// 使用生成器异步代码编程
15.Modules(语言层面的模块化标准)
16.async await(promise语法糖,解决异步编程嵌套过深)