系列文章目录
提示:阅读本章之前,请先阅读目录
文章目录
- 系列文章目录
- 前言
- let
- const 常量
- 数组解构
- 对象结构
- 模板字符串
- 对象简写
- 箭头函数
- 箭头函数应用场景
- 函数参数的默认值
- rest 参数
- 扩展运算符
- Symbol
- Symbol 使用
- 迭代器 iterator
- 对象的迭代器
- 生成器
- 生成器传参
- 生成器应用实例
- Promise
- Promise 封装读取文件
- Promise then 返回类型
- Promise 的catch
- Set 集合
- Set 运算
- Map
- class
- Class 静态成员 static
- Class 的 extends 继承父类
- Class 对父类的方法完全重写
- Class 的get和set
- 数值扩展
- 对象扩展
- 模块化 import 和 export
- 浏览器标签引入模块
- includes 判断数组是否存在某个值
- 幂运算 **
- async 和 await
- ES8对象扩展
- ES9 正则命名分组 <key-name>
- ES9 正则的正反断言
- ES9 正则的dotAll 模式
- fromEntries 二维数组转换为对象
- trimStart 和 trimEnd
- flat 和 flatMap
- ES11 私有属性
- Proimse 的 allSettled
- ES11 的正则matchAll
- ES11 可选链操作符
- ES11 动态导入
- ES11 BigInt
- ES11 的globalThis
前言
let
// 1. 声明变量
let a;
let b,c,d;
let e = 999;
let f = 1, g = "888", k = [1,2,3], p = { name: 123 }
// 2. 不可重复声明
let r = 1;
let r = "99"
// 3. 不存在变量提升
console.log(boss)
let boss = "smobee"
// 4. 作用域
{
let school = "smobee"
}
console.log("这里无法拿到", school)
// 5. 不影响作用域链
{
let student = "smobee"
function getName() {
console.log("我这里可以拿到", student)
}
getName()
}
let 练习
这里的 i 用了let,就有作用域的效果,如果用var,就会拿的全局的var
const 常量
// 1. 不可修改(替换指向的内存地址)
const a = "123";
// 报错
a = 111;
// 2. 有作用域
{
const b = 123;
}
console.log("我拿不到", b)
// 3. 一般使用大写
const SCHOOL = "smobee";
// 4. 对象或数组,可以更改属性 或 数组操作
const obj = { name: "123" }
obj.name = "9999"
const list = [1,2,3]
list.push(4)
// 5. 一定要赋初始值
const koo = 123;
数组解构
const list = [1,2,3,4]
let [one, two, three, four] = list
console.log(one)
对象结构
const obj = {
name: "123",
age: 88,
game: function() {
return 9999999
}
}
let { name, age, game } = obj
console.log(name)
game()
模板字符串
// 1. 也是字符串
let name = `99999999999`
console.log(type name)
// 2. 可以直接换行
let template = `
<div>hhhhhhhh</div>
`
// 3. 变量拼接
let student = "smobee"
let text = `${student},这是我的名字`
对象简写
let name = "123"
const obj {
name,
ok: function() {
return "我不是简写的对象"
},
okk() {
return "我就是简写"
}
}
箭头函数
// 1. this的执行,是当前作用域
const a = () => {
console.log(this.name)
}
const b = function() {
console.log(this.name)
}
window.name = "我是window的name"
let obj = {
name: "我是obj的name"
}
// 输出的是 "我是window的name"
a.call(obj)
// 输出的是 "我是obj的name"
b.call(obj)
// 2. 不能作为构造函数实例对象
const c = (a) => {
return "999" + a
}
// 不行
let obj = new c(888);
// 3. 简写
const d = h => {
return 1+1
}
const p = h => 1+1
// 4. 不能使用arguments参数
const kkk = () => {
console.log("我是没有arguments参数的", arguments)
}
箭头函数应用场景
// 1. this的指向
const element = document.getElementById("app")
element.addEventListener("click", function() {
const _this = this
setTimeout(() => {
// 这里的this,指向了element
this.style.background = "red"
}, 2000)
setTimeout(function() {
// 这里的this,指向了window,拿不到,所以要用_this
_this.style.background = "red"
}, 2000)
})
// 2. 简化语法
// 普通写法
const arr = [1,2,3,4,5,6,7]
const newARR = arr.filter(function(item) {
return item % 2 == 0
})
//简化
const newARR = arr.filter(item => item % 2 == 0)
})
函数参数的默认值
// 1. 参数赋值默认值
const objA = function(a = "hello", b, c) {
console.log("参数,可以给默认值")
}
// 2. 解构参数
const objB = function({ username="smobee", age=99 }) {
console.log("使用解构+默认值")
}
// 可以不传,会自动使用默认值
objB({ username: "ooooo" })
rest 参数
// ES5
const objA = function() {
console.log("我可以拿到所有参数,但是我返回的是一个对象", arguments)
}
objA(1,2,3,4,5)
// ES6
const objB = function(a, b, c, ...args) {
console.log("我可以拿到所有参数,但是我返回的是一个数组")
}
objB(1,2,3,4,5,6,7,8)
扩展运算符
// 1. 数组的合并
const arrA = [1,2,3,4,5]
const arrB = [8,9,10]
consty arrC = [...arrA, ...arrB]
// 2. 数组的拷贝,如果是引用对象,是浅拷贝
const arrD = [...arrA]
// 3. 将伪数组,转换为真数组
const arrE = document.querySelectorAll("div")
const divA = [...arrE]
Symbol
// 1. 创建symbol,返回值,是唯一的,主要是为了解决命名冲突
const s1 = Symbol()
const s2 = Symbol()
const s3 = Symbol("Smobee")
const s4 = Symbol("Smobee")
console.log("s1,不会等于,s2", s1 == s2)
console.log("s3,不会等于,s4", s3 == s4)
// 2. 全局定义,重复变量名
const s5 = Symbol.for("smobee")
const s6 = Symbol.for("smobee")
console.log("s5,等于,s6", s5 == s6)
// 3. 不能与其他数据类型进行运算
console.log("不能与其他数据类型进行运算", s5 + s6)
Symbol 使用
// 1. 给对象,安全的添加属性
const keyname = {
testA: Symbol(),
testB: Symbol()
}
const school = {
name: "哈哈哈哈哈",
age: 99999,
address: "13246789"
}
school[keyname.testA] = "我可以快速安全的添加属性,不怕重复"
school[keyname.testB] = function() { return "xxxx" }
// 2. 直接在对象里面使用Symbol,创建属性
const studnet = {
name: "smobee",
[Symbol("meili")]: function() {
return 999999
},
[Symbol("hahahah")]: 9999
}
console.log(student[Symbol("hahahah")])
迭代器 iterator
const arr = ["xiaoming", "xiaofeng", "xiaohong"]
// 数组里面有个属性叫,Symbol.iterator
const iterator = arr[Symbol.iterator]()
// 拿到iterator,里面就有一个next,每次都可以读取一个值,不断的调用next,指针就会不断往后移,直到没有值,返回value:undefined,done:true
console.log("每次取值", iterator.next())
console.log("每次取值", iterator.next())
console.log("每次取值", iterator.next())
console.log("每次取值", iterator.next())
// for of 循环,可以直接取值
const arr = ["猪八戒", "孙悟空"]
for(let name of arr) {
console.log("我可以拿到名字", name)
}
// for in 循环,拿到的是下标
const arr = ["猪八戒", "孙悟空"]
for(let index in arr) {
console.log("我可以拿到下标", index)
}
对象的迭代器
const obj = {
name: "hello",
arr: ["孙悟空", "唐僧", "猪八戒"],
[Symbol.iterator]: function() {
let index = 0;
return {
next: () => {
let result = {}
if (index < this.arr.length) {
result = { value: this.arr[index], done: false}
index++;
} else {
result = { value: undefine, done: true}
}
return result;
}
}
}
}
for (let name of obj) {
console.log(name)
}
生成器
// 创建生成器,异步函数
function * gen() {
console.log("第一步")
yield "小明";
console.log("第二步")
yield "小兰";
console.log("第三步")
yield "小黄";
console.log("第四步")
}
const iterator = gen();
// 输出 第一步
iterator.next();
// 输出 第二步
iterator.next();
for (let name of iterator) {
console.log("我是输出姓名,小明", name)
}
生成器传参
function * gen(arg) {
console.log("我拿到arg了", arg)
const yld = yield "小明";
console.log("我拿到了yld", yld);
}
const iterator = gen("我是arg参数")
iterator.next("我是传给yld的")
生成器应用实例
function one() {
setTimeout(() => {
console.log("我是异步的")
iterator.next();
}, 2000)
}
function two() {
setTimeout(() => {
console.log("我是异步的")
iterator.next();
}, 2000)
}
function three() {
setTimeout(() => {
console.log("我是异步的")
iterator.next();
}, 2000)
}
function * gen() {
yield one();
yield two();
yield three();
}
const iterator = gen();
iterator.next();
搭配传参
function one() {
setTimeout(() => {
console.log("我是异步的")
const data = [1,2,3]
iterator.next(data);
}, 2000)
}
function two() {
setTimeout(() => {
const data = [1,2,3]
console.log("我是异步的")
iterator.next(data);
}, 2000)
}
function three() {
setTimeout(() => {
console.log("我是异步的")
iterator.next();
}, 2000)
}
function * gen() {
const one = yield one();
const two = yield two(one);
const three = yield three(two);
}
const iterator = gen();
iterator.next();
Promise
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 1. 成功 用resolve 返回
resolve("我是成功的数据")
// 2. 失败 用reject 返回
reject("我是失败")
}, 2000)
})
p.then((data) => {
console.log("我是成功的")
}, (err) => {
console.log("我是失败的")
})
Promise 封装读取文件
const p = new Promise((resolve, reject) => {
fs.readFile("./test.txt", (err, data) => {
if (!err) reject("无法获取到文件")
resolve(data.toString())
})
})
Promise then 返回类型
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 1. 成功 用resolve 返回
resolve("我是成功的数据")
// 2. 失败 用reject 返回
reject("我是失败")
}, 2000)
})
// 1. 返回的是成功,值是123
const res = p.then((data) => {
console.log("我是成功的")
return 123;
}, (err) => {
console.log("我是失败的")
})
// 2. 返回的是失败,值是999
const res = p.then((data) => {
console.log("我是成功的")
}, (err) => {
console.log("我是失败的")
return "999";
})
// 3. 返回的是一个Promise,成功与失败,和这个Promise返回的一致
const res = p.then((data) => {
console.log("我是成功的")
return new Promise((resolve, reject) => {
resolve("我返回的是成功状态,并且值就是我")
})
}, (err) => {
console.log("我是失败的")
})
// 4. 链式回调
p.then(() => [
console.log("我这里返回的是一个Promise")
}).then(() => {
console.log("所以,我可以继续then")
})
Promise 的catch
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 1. 成功 用resolve 返回
resolve("我是成功的数据")
// 2. 失败 用reject 返回
reject("我是失败")
}, 2000)
})
// 1. 返回的是成功,值是123
const res = p.then((data) => {
console.log("我是成功的")
return 123;
}).catch((err) => {
console.log("我是失败的")
})
Set 集合
const testSet = new Set(["a", "b", "c"])
// 1. 大小
console.log(testSet.size)
// 2. 增加
testSet.add("d")
// 3. 删除
testSet.delete("b")
// 4. 清空
testSet.clear()
// 5. 检查有无值
testSet.has("d")
// 6. 支持 for...of
for(let name of testSet) {}
Set 运算
// 1. 去重
const arr = [1,1,1,2,3,4,5,6,7,8,9,9,9]
const newArr = [...new Set()]
// 2. 交集
const arr2 = [1,2,3]
const newArr2 = [...new Set(arr)].filter( item => new Set(arr2).has(item))
// 3. 并集
const newArr3 = [...new Set([...arr, ...arr2])]
// 4. 差集
const newArr4 = [...new Set(arr)].filter( item => !(new Set(arr2).has(item)))
Map
// 1. 创建Map
const m = new Map()
// 2. 添加
m.set("name", "xiaoming")
m.set("obj", {
name: "123"
})
const key = {
school: "22222"
}
m.set(key, 123)
// 2. 删除
m.delete("name")
// 3. 读取
m.get(key)
m.get("name")
// 4. 大小
console.log(m.size)
// for...of
for(let arr of m) {}
class
// ES5 实例化对象
function Phone(value) {
console.log("我拿到value了")
}
Phone.prototype.call = function() {
console.log("我被调用了")
}
const phone = new Phone("123")
phone.call()
// ES6 实例化对象
class Tel {
constructor(value) {
console.log("我也拿到了value")
}
call() {
console.log("我就是那个call")
}
}
Class 静态成员 static
class Phone {
static name = "123";
static change() {
console.log("hello")
}
}
Class 的 extends 继承父类
class Phone {
constructor(one, two) {
this.one = one
this.two = two
}
call() {
console.log("大家好,我是父类的call")
}
}
class NewPhone extends Phone {
constructor(one, two, three ,four) {
// super 就是调用父类的constructor
super(one, two)
this.three = three
this.four = four
}
photo() {}
}
const newphone = new NewPhone(1,2,3,4);
newphone.call()
Class 对父类的方法完全重写
class Phone {
constructor(one, two) {
this.one = one
this.two = two
}
call() {
console.log("大家好,我是父类的call")
}
}
class NewPhone extends Phone {
constructor(one, two, three ,four) {
// super 就是调用父类的constructor
super(one, two)
this.three = three
this.four = four
}
photo() {}
call() {
// super(),无法这样调用父类原有的方法
console.log("我就是对父类的call,完全重写,替换掉")
}
}
Class 的get和set
class txt {
get title() {
console.log("有人读取了我哦")
return "我会返回给调用的人"
}
set title(newValue) {
console.log("有人给我赋值了")
this.title = newValue
}
}
const t = new txt();
t.title
t.title = "123"
数值扩展
// 1. Number.EPSILON 是JavaScript 最小精度
function equal(a, b) {
if(Math.abs(1-b) < Number.EPSILON) {
return true
} else {
return false
}
}
console.log(0.1 + 0.2 == 0.3) // false
consoel.log(equal(0.1, 0.2)) // true
// 2. 二进制,八进制,十六进制
const b = 0b1010
const o = 0o777
const c = 12345
const x = 0xff
// 3. Number.isFinite 判断一个数,是不是有限的
console.log(Number.isFinite(100/0)) // false
console.log(Number.isFinite(100000)) // true
console.log(Number.isFinite(Infinity)) // true
// 4. Number.isNaN,一个数字他本来应该是个数字,结果不是数字,他就是NaN
console.log(Number.isNaN(123)) // true
console.log(Number.isNaN(100/ppppp)) // false
// 5. Number.parseInt 对内容,转为整数
console.log(Number.parseInt("123pppoooo3")) // 123
// 6. Number.parseFloat 对内容,转为小数点
console.log(Number.parseInt("123.99999pppoooo3")) // 123.99999
// 7. Number.isInteger判断一个数,是不是整数
console.log(Number.isInteger(5.666)) // false
// 8. Math.trunc 将小数抹除
console.log(Math.trunc(1.233333))
// 9. Math.sign 判断一个数字,是不是正数
console.log(Math.sign(33333)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-99999)) // -1
对象扩展
// 1. Object.is 两个值是否完全相等
console.log(Object.is(1,1)) // true
console.log(Object.is(1,100)) // false
console.log(Object.is(NaN,NaN)) // true
console.log(NaN === NaN)) // false
// 2. Object.assign,合并对象
const o1 = {
name: "我是被覆盖的",
age: 999,
color: "red"
}
const o2 = {
name: "我将会是最新的"
}
const o3 = Object.assign(o1, o2)
// 3. Object.setPrototypeOf 设置对象的原型对象
Object.setPrototypeOf(o1, o2)
// 4. Object.getPrototypeOf 获取对象的原型对象
Object.getPrototypeOf(o1)
模块化 import 和 export
分别暴露
export let school = "hello";
export const obj = {
name: 123
}
export function phone() {
return 123
}
import * as boss from "./test.js"
console.log(boss)
统一暴露
let school = "hello";
const obj = {
name: 123
}
function phone() {
return 123
}
export { school, obj, phone }
默认暴露
let school = "hello";
const obj = {
name: 123
}
function phone() {
return 123
}
export default { school, obj, phone }
调用的时候,要使用default,,或者对象解构
import { school } from "./test.js"
import * as boss from "./test.js"
boss.school
浏览器标签引入模块
<script type="module">
import boss from "test.js"
</script>
<script src="test.js" type="module">
</script>
includes 判断数组是否存在某个值
const arr1 = [1,2,3,4,5]
console.log(arr1.includes(1)) // true
console.log(arr1.includes(10000)) // false
幂运算 **
// 1. Math.pow(值,数)
console.log(Math.pow(2, 10))
// 2. **
console.log(2 ** 10)
async 和 await
async function hello() {
// 1. 返回一个成功的Promise, 相当于返回了resolve
return "hhh";
// 2. 抛出异常,相当于返回了reject
throw new "9999";
// 3. 返回Promise
return new Promise((resolve, reject) => {})
}
const res = hello()
res.then(() => {}).catch(() => {})
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("await拿到的就是我")
}, 2000)
})
async function phone() {
// 1. 如果await里面返回的是异常,那么则需要用try..catch接受
tru {
const res = await p;
} catch(e) {
console.log(e)
}
return res
}
ES8对象扩展
const ojb = {
name: 123,
age: 123
}
// 1. 获取所有的key
console.log(Object.keys(ojb))
// 2. 获取所有的value
console.log(Object.values(ojb))
// 3. 返回一个数组,是value,和,key
console.log(Object.entries(obj))
// 4. 获取对象的描述对象
console.log(Object.getOwnPropertyDesciptors)
ES9 正则命名分组
const str = "<a src="http://www.baidu.com">大家好啊,我是内容</a>";
const reg = /<a src="(?<url>.*)">(?<txt>.*)</a>/;
const res = reg.exec(str);
// 输出 里面有一个groups,就是键值对 { url: "xxxx", txt: "123" }
ES9 正则的正反断言
const str = "www123999dddddd9922222kkkkk";
// 1. 正向断言,获取22222
const reg1 = /\d+(?=k)/;
reg1.exec(str) // 输出222222
// 2. 反向断言
cosnt reg2 = /(?<=d99)\d+/;
reg2.exec(str) // 输出222222
ES9 正则的dotAll 模式
正则表达式,最后加个s
fromEntries 二维数组转换为对象
const arr = [
["name", "xmf"],
["age", 22]
]
Object.fromEntries(arr);
// 最后转换为
// { name: "xmf", age: 22 }
trimStart 和 trimEnd
const str = " 123 "
// 1. 清除开头的空格
console.log(str.trimStart())
// 2. 清除结尾的空格
console.log(str.trimEnd())
flat 和 flatMap
// 1. 将二维数组,转换为,一维数组
const arr1 = [1,2,3,4,5,[8,9,0]]
console.log(arr1.flat()) // 1,2,3,4,5,8,9,0
// 2. 将三维数组,转为,一维数组
console.log(arr1.flat(2)) // 1,2,3,4,5,8,9,0
// 3. flatMap
const arr2 = [1,2,3,4,5,6,7]
console.log(arr2.flatMap( item => [item * 10])) // 10,20,30,40,50,60,70
ES11 私有属性
class Phone {
let name = "123";
let #age = 99;
getAge() {
// 只有class内部才能获取
return this.#age;
}
}
const phone = new Phone();
console.log("外部是无法访问的",phone.#age)
Proimse 的 allSettled
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("我是成功的")
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("我是成功的")
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("我是失败的")
}, 2000)
})
// 1. 不管里面是否成功或者失败,都是返回成功
const res1 = Promise.allSettled([p1, p2, p3])
// 2. 里面只要有一个失败了,就会返回失败,并且那个值,就是失败的Promise返回的
const res2 = Promise.all([p2, p3])
allSettled
all
ES11 的正则matchAll
ES11 可选链操作符
function phone(config) {
// 旧的写法
console.log(config && config.db && config.db.host)
// 新的写法
console.log(config?.db?.host)
}
phone({
db: {
host: "localhost"
}
})
ES11 动态导入
export default function hello() {
return 9999
}
import("./test.js").then( module => {
module.hello()
})
ES11 BigInt
const max = Number.MAX_SAFE_INTEGER;
console.log(BigInt(max) + BigInt(3)) // ........3n
ES11 的globalThis
全局对象
console.log(globalThis)