ES6~ES13新特性(二)
1 模板字符串的详解
字符串模板基本使用
标签模板字符串使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const name = "why"
const age = 18
// 1.基本用法
// 1.1.ES6之前
// const info = "my name is" + name + ", age is " + age
// 1.2.ES6之后
const info = `my name is ${name}, age is ${age}`
console.log(info)
// 2.标签模板字符串的用法
function foo(...args) {
console.log("参数:", args)
}
// foo("why", 18, 1.88)
foo`my name is ${name}, age is ${age}, height is ${1.88}`
</script>
</body>
</html>
React的styled-components库
2 ES6函数的增强用法
函数的默认参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 注意: 默认参数是不会对null进行处理的
function foo(arg1 = "我是默认值", arg2 = "我也是默认值") {
// 1.两种写法不严谨
// 默认值写法一:
// arg1 = arg1 ? arg1: "我是默认值"
// 默认值写法二:
// arg1 = arg1 || "我是默认值"
// 2.严谨的写法
// 三元运算符
// arg1 = (arg1 === undefined || arg1 === null) ? "我是默认值": arg1
// ES6之后新增语法: ??
// arg1 = arg1 ?? "我是默认值"
// 3.简便的写法: 默认参数
console.log(arg1)
}
foo(123, 321)
foo()
foo(0)
foo("")
foo(false)
foo(null)
foo(undefined)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.注意一: 有默认参数的形参尽量写到后面
// 2.有默认参数的形参, 是不会计算在length之内(并且后面所有的参数都不会计算在length之内)
// 3.剩余参数也是放到后面(默认参数放到剩余参数的前面)
function foo(age, name = "why", ...args) {
console.log(name, age, args)
}
foo(18, "abc", "cba", "nba")
console.log(foo.length)
</script>
</body>
</html>
函数默认值的补充
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.解构的回顾
// const obj = { name: "why" }
// const { name = "kobe", age = 18 } = obj
// 2.函数的默认值是一个对象
// function foo(obj = { name: "why", age: 18 }) {
// console.log(obj.name, obj.age)
// }
function foo({ name, age } = { name: "why", age: 18 }) {
console.log(name, age)
}
function foo({ name = "why", age = 18 } = {}) {
console.log(name, age)
}
foo()
</script>
</body>
</html>
函数的剩余参数
函数箭头函数的补充
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.function定义的函数是有两个原型的:
// function foo() {}
// console.log(foo.prototype) // new foo() -> f.__proto__ = foo.prototype
// console.log(foo.__proto__) // -> Function.prototype
// 2.箭头函数是没有显式原型
// 在ES6之后, 定义一个类要使用class定义
var bar = () => {}
// console.log(bar.__proto__ === Function.prototype)
// 没有显式原型
// console.log(bar.prototype)
// var b = new bar()
</script>
</body>
</html>
3 展开运算符的使用
展开语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.基本演练
// ES6
const names = ["abc", "cba", "nba", "mba"]
const str = "Hello"
// const newNames = [...names, "aaa", "bbb"]
// console.log(newNames)
function foo(name1, name2, ...args) {
console.log(name1, name2, args)
}
foo(...names)
foo(...str)
// ES9(ES2018)
const obj = {
name: "why",
age: 18
}
// 不可以这样来使用
// foo(...obj) // 在函数的调用时, 用展开运算符, 将对应的展开数据, 进行迭代
// 可迭代对象: 数组/string/arguments
const info = {
...obj,
height: 1.88,
address: "广州市"
}
console.log(info)
</script>
</body>
</html>
浅拷贝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const obj = {
name: "why",
age: 18,
height: 1.88,
friend: {
name: "curry"
}
}
// 1.引用赋值
// const info1 = obj
// 2.浅拷贝
// const info2 = {
// ...obj
// }
// info2.name = "kobe"
// console.log(obj.name)
// console.log(info2.name)
// info2.friend.name = "james"
// console.log(obj.friend.name)
// 3.深拷贝
// 方式一: 第三方库
// 方式二: 自己实现
// function deepCopy(obj) {}
// 方式三: 利用先有的js机制, 实现深拷贝JSON
const info3 = JSON.parse(JSON.stringify(obj))
console.log(info3.friend.name)
info3.friend.name = "james"
console.log("info3.friend.name:", info3.friend.name)
console.log(obj.friend.name)
</script>
</body>
</html>
引用赋值
浅拷贝
深拷贝
数值的表示
4 Symbol类型用法
Symbol的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// ES6之前存在的问题
// const obj = {
// name: "why",
// fn: "aaa"
// }
// // 添加一个新的属性 name
// function foo(obj) {
// obj.why = function() {}
// }
// foo(obj)
// console.log(obj.fn)
// ES6之后可以使用Symbol生成一个独一无二的值
const s1 = Symbol()
// const info = { name: "why" }
const obj = {
[s1]: "aaa"
}
console.log(obj)
const s2 = Symbol()
obj[s2] = "bbb"
console.log(obj)
function foo(obj) {
const sKey = Symbol()
obj[sKey] = function() {}
delete obj[sKey]
}
foo(obj)
</script>
</body>
</html>
Symbol作为属性名
相同值的Symbol
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const s1 = Symbol() // aaa
const s2 = Symbol() // bbb
// 1.加入对象中
const obj = {
name: "why",
age: 18,
[s1]: "aaa",
[s2]: "bbb"
}
// const obj1 = {}
// obj1[s1] = "aaa"
// obj2[s2] = "bbb"
// const obj2 = {}
// Object.defineProperty(obj, s1, {
// value: "aaa"
// })
// 2.获取symbol对应的key
console.log(Object.keys(obj))
console.log(Object.getOwnPropertySymbols(obj))
const symbolKeys = Object.getOwnPropertySymbols(obj)
for (const key of symbolKeys) {
console.log(obj[key])
}
// 3.description
// 3.1.Symbol函数直接生成的值, 都是独一无二
const s3 = Symbol("ccc")
console.log(s3.description)
const s4 = Symbol(s3.description)
console.log(s3 === s4)
// 3.2. 如果相同的key, 通过Symbol.for可以生成相同的Symbol值
const s5 = Symbol.for("ddd")
const s6 = Symbol.for("ddd")
console.log(s5 === s6)
// 获取传入的key
console.log(Symbol.keyFor(s5))
</script>
</body>
</html>
5 数据结构-Set集合
Set的基本使用
Set的常见方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.创建Set
const set = new Set()
console.log(set)
// 2.添加元素
set.add(10)
set.add(22)
set.add(35)
set.add(22)
console.log(set)
const info = {}
const obj = {name: "obj"}
set.add(info)
set.add(obj)
set.add(obj)
console.log(set)
// 3.应用场景: 数组的去重
const names = ["abc", "cba", "nba", "cba", "nba"]
// const newNames = []
// for (const item of names) {
// if (!newNames.includes(item)) {
// newNames.push(item)
// }
// }
// console.log(newNames)
const newNamesSet = new Set(names)
const newNames = Array.from(newNamesSet)
console.log(newNames)
// 4.Set的其他属性和方法
// 属性
console.log(set.size)
// 方法
// 4.1. add方法
set.add(100)
console.log(set)
// 4.2. delete方法
set.delete(obj)
console.log(set)
// 4.3. has方法
console.log(set.has(info))
// 4.4. clear方法
// set.clear()
// console.log(set)
// 4.5. forEach
set.forEach(item => console.log(item))
// 5.set支持for...of
for (const item of set) {
console.log(item)
}
</script>
</body>
</html>
WeakSet使用
WeakSet的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.Weak Reference(弱引用)和Strong Reference(强引用)
let obj1 = { name: "why" }
let obj2 = { name: "kobe" }
let obj3 = { name: "jame" }
// let arr = [obj1, obj2, obj3]
// obj1 = null
// obj2 = null
// obj3 = null
// const set = new Set(arr)
// arr = null
// 2.WeakSet的用法
// 2.1.和Set的区别一: 只能存放对象类型
const weakSet = new WeakSet()
weakSet.add(obj1)
weakSet.add(obj2)
weakSet.add(obj3)
// 2.2.和Set的区别二: 对对象的引用都是弱引用
// 3.WeakSet的应用
const pWeakSet = new WeakSet()
class Person {
constructor() {
pWeakSet.add(this)
}
running() {
if (!pWeakSet.has(this)) {
console.log("Type error: 调用的方式不对")
return
}
console.log("running~")
}
}
let p = new Person()
// p = null
p.running()
const runFn = p.running
runFn()
const obj = { run: runFn }
obj.run()
</script>
</body>
</html>
6 数据结构-Map映射
Map的基本使用
Map的常用方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const info = { name: "why" }
const info2 = { age: 18 }
// 1.对象类型的局限性: 不可以使用复杂类型作为key
// const obj = {
// address: "北京市",
// [info]: "哈哈哈",
// [info2]: "呵呵呵"
// }
// console.log(obj)
// 2.Map映射类型
const map = new Map()
map.set(info, "aaaa")
map.set(info2, "bbbb")
console.log(map)
// 3.Map的常见属性和方法
// console.log(map.size)
// 3.1. set方法, 设置内容
map.set(info, "cccc")
console.log(map)
// 3.2. get方法, 获取内容
// console.log(map.get(info))
// 3.3. delete方法, 删除内容
// map.delete(info)
// console.log(map)
// 3.4. has方法, 判断内容
// console.log(map.has(info2))
// 3.5. clear方法, 清空内容
// map.clear()
// console.log(map)
// 3.6. forEach方法
// map.forEach(item => console.log(item))
// 4.for...of遍历
for (const item of map) {
const [key, value] = item
console.log(key, value)
}
</script>
</body>
</html>
WeakMap的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let obj1 = { name: "why" }
let obj2 = { name: "kobe" }
// 1.WeakMap的基本使用
const weakMap = new WeakMap()
// weakMap.set(123, "aaa")
weakMap.set(obj1, "aaa")
weakMap.set(obj2, "bbb")
obj1 = null
obj2 = null
</script>
</body>
</html>
WeakMap的应用
ES6其他知识点说明
ES7~ES13新特性(三)
1 ES7新增特性解析
ES7 - Array Includes(已学)
ES7 –指数exponentiation运算符(已学)

2 ES8新增特性解析
ES8 Object values
ES8 Object entries
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const obj = {
name: "why",
age: 18,
height: 1.88,
address: "广州市"
}
// 1.获取所有的key
const keys = Object.keys(obj)
console.log(keys)
// 2.ES8 Object.values
const values = Object.values(obj)
console.log(values)
// 3.ES8 Object.entries
// 3.1. 对对象操作
const entries = Object.entries(obj)
console.log(entries)
for (const entry of entries) {
const [key, value] = entry
console.log(key, value)
}
// 3.2. 对数组/字符串操作(了解)
console.log(Object.entries(["abc", "cba"]))
console.log(Object.entries("Hello"))
</script>
</body>
</html>
ES8 - String Padding
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1 class="card"></h1>
<script>
// padStart和padEnd
// 1.应用场景一: 对时间进行格式化
// const minute = "15".padStart(2, "0")
// const second = "6".padStart(2, "0")
// console.log(`${minute}:${second}`)
// 2.应用场景二: 对一些敏感数据格式化
let cardNumber = "132666200001018899"
const sliceNumber = cardNumber.slice(-4)
cardNumber = sliceNumber.padStart(cardNumber.length, "*")
const cardEl = document.querySelector(".card")
cardEl.textContent = cardNumber
</script>
</body>
</html>
ES8 - Trailing Commas
ES8 - Object Descriptors
ES9新增知识点
3 ES10新增特性解析
ES10 - flat flatMap
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.flat的使用:
// 将一个数组, 按照制定的深度遍历, 将遍历到的元素和子数组中的元素组成一个新的数组, 进行返回
// const nums = [10, 20, [111, 222], [333, 444], [[123, 321], [231, 312]]]
// const newNums1 = nums.flat(1)
// console.log(newNums1)
// const newNums2 = nums.flat(2)
// console.log(newNums2)
// 2.flatMap的使用:
// 1> 对数组中每一个元素应用一次传入的map对应的函数
const messages = [
"Hello World aaaaa",
"Hello Coderwhy",
"你好啊 李银河"
]
// 1.for循环的方式:
// const newInfos = []
// for (const item of messages) {
// const infos = item.split(" ")
// for (const info of infos) {
// newInfos.push(info)
// }
// }
// console.log(newInfos)
// 2.先进行map, 再进行flat操作
// const newMessages = messages.map(item => item.split(" "))
// const finalMessages = newMessages.flat(1)
// console.log(finalMessages)
// 3.flatMap
const finalMessages = messages.flatMap(item => item.split(" "))
console.log(finalMessages)
</script>
</body>
</html>
ES10 - Object fromEntries
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.对象
// const obj = {
// name: "why",
// age: 18,
// height: 1.88
// }
// const entries = Object.entries(obj)
// const info = Object.fromEntries(entries)
// console.log(info)
// 2.应用
const searchString = "?name=why&age=18&height=1.88"
const params = new URLSearchParams(searchString)
console.log(params.get("name"))
console.log(params.get("age"))
console.log(params.entries())
// for (const item of params.entries()) {
// console.log(item)
// }
const paramObj = Object.fromEntries(params)
console.log(paramObj)
</script>
</body>
</html>
ES10 - trimStart trimEnd
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const message = " Hello World "
console.log(message.trim())
console.log(message.trimStart())
console.log(message.trimEnd())
</script>
</body>
</html>
ES10 其他知识点
4 ES11新增特性解析
ES11 - BigInt
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
console.log(Number.MAX_SAFE_INTEGER)
const num1 = 9007199254740992n
const num2 = 9007199254740993n
console.log(num1, num2)
</script>
</body>
</html>
ES11 - Nullish Coalescing Operator
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let info = undefined
// info = info || "默认值"
// console.log(info)
// ??: 空值合并运算符
info = info ?? "默认值"
console.log(info)
</script>
</body>
</html>
ES11 - Optional Chaining
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const obj = {
name: "why",
friend: {
name: "kobe",
// running: function() {
// console.log("running~")
// }
}
}
// 1.直接调用: 非常危险
// obj.friend.running()
// 2.if判断: 麻烦/不够简洁
// if (obj.friend && obj.friend.running) {
// obj.friend.running()
// }
// 3.可选链的用法: ?.
obj?.friend?.running?.()
</script>
</body>
</html>
ES11 - Global This(已学)
ES11 - for..in标准化
ES11 其他知识点
5 ES12新增特性解析
ES12 - FinalizationRegistry
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let obj = { name: "why", age: 18 }
let info = { name: "kobe", age: 30 }
const finalRegistry = new FinalizationRegistry((value) => {
console.log("某一个对象被回收了:", value)
})
finalRegistry.register(obj, "why")
finalRegistry.register(info, "kobe")
// obj = null
info = null
</script>
</body>
</html>
ES12 - WeakRefs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let info = { name: "why", age: 18 }
let obj = new WeakRef(info)
let obj2 = new WeakRef(info)
const finalRegistry = new FinalizationRegistry(() => {
console.log("对象被回收~")
})
finalRegistry.register(info, "info")
setTimeout(() => {
info = null
}, 2000)
setTimeout(() => {
console.log(obj.deref().name, obj.deref().age)
}, 8000)
</script>
</body>
</html>
ES12 - logical assignment operators
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 赋值运算符
// const foo = "foo"
let counter = 100
counter = counter + 100
counter += 50
// 逻辑赋值运算符
function foo(message) {
// 1.||逻辑赋值运算符
// message = message || "默认值"
// message ||= "默认值"
// 2.??逻辑赋值运算符
// message = message ?? "默认值"
message ??= "默认值"
console.log(message)
}
foo("abc")
foo()
// 3.&&逻辑赋值运算符
let obj = {
name: "why",
running: function() {
console.log("running~")
}
}
// 3.1.&&一般的应用场景
// obj && obj.running && obj.running()
// obj = obj && obj.name
obj &&= obj.name
console.log(obj)
</script>
</body>
</html>
ES12其他知识点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const message = "my name is why, why age is 18"
const newMessage = message.replace("why", "kobe")
const newMessage2 = message.replaceAll("why", "kobe")
console.log(newMessage)
console.log(newMessage2)
</script>
</body>
</html>
6 ES13新增特性解析
ES13 - method .at()
ES13 - Object.hasOwn(obj, propKey)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// const obj = {
// name: "why",
// age: 18,
// // 1.和hasOwnProperty的区别一: 防止对象中也有一个自己的hasOwnProperty方法
// hasOwnProperty: function() {
// return "abc"
// },
// __proto__: {
// address: "广州市"
// }
// }
// console.log(obj.name, obj.age)
// console.log(obj.address)
// console.log(obj.hasOwnProperty("name"))
// console.log(obj.hasOwnProperty("address"))
// console.log(Object.hasOwn(obj, "name"))
// console.log(Object.hasOwn(obj, "address"))
// 2.和hasOwnProperty的区别二:
const info = Object.create(null)
info.name = "why"
// console.log(info.hasOwnProperty("name"))
console.log(Object.hasOwn(info, "name"))
</script>
</body>
</html>
ES13 - New members of classes
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class Person {
// 1.实例属性
// 对象属性: public 公共 -> public instance fields
height = 1.88
// 对象属性: private 私有: 程序员之间的约定
// _intro = "name is why"
// ES13对象属性: private 私有: 程序员之间的约定
#intro = "name is why"
// 2.类属性(static)
// 类属性: public
static totalCount = "70亿"
// 类属性: private
static #maleTotalCount = "20亿"
constructor(name, age) {
// 对象中的属性: 在constructor通过this设置
this.name = name
this.age = age
this.address = "广州市"
}
// 3.静态代码块
static {
console.log("Hello World")
console.log("Hello Person")
}
}
const p = new Person("why", 18)
console.log(p)
// console.log(p.name, p.age, p.height, p.address, p.#intro)
// console.log(Person.#maleTotalCount)
</script>
</body>
</html>