后盾人JS -- 类类的
不错
类的内部的工作机制就是原型操作
class声明的方法为什么不能遍历
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// function Hd(){}
// let hd = new Hd()
// hd.prototype.show = function(){
// this.name = name
// }
// for(const key in h){
// if(h.hasOwnProperty(key)){
// console.log(key)
// }
// console.log(key)
// }
class User{
constructor(name){
this.name = name
}
show(){}
}
let u = new User(
"向军"
)
console.dir(User)
console.log(
JSON.stringify(
Object.getOwnPropertyDescriptor(User.prototype,"show",null,2)
)
)
for(const key in u){
console.log(key)
}
</script>
</body>
</html>
在所有可以支持严格模式的语言中,最好都用严格模式(我觉得也是)
静态属性使用
static只保存一份到类中,如果所有属性共用就可以写成静态属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Web(url){
this.url = url
}
Web.url = "hdcms.com"
let hd = new Web("houdunren.com")
console.log(hd)
console.dir(Web)
class Request{
host = "https://www.houdunren.com"
}
let obj = new Request()
console.log(obj)
let obj2 = new Request()
obj.host = "https://baidu.com"
console.log(obj2)
</script>
</body>
</html>
静态方法的实现原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function User(){
this.show = function(){
console.log("prototype.show")
}
}
User.__proto__.show = function(){
console.log("static.show")
}
let hd = new User()
hd.show()
</script>
</body>
</html>
静态属性练习之课程管理类
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const data = [
{name:"js" ,price:100},
{name:"mysql",price:212},
{name:"vue.js",price:98}
]
class Lesson{
constructor(data){
this.model = data
}
get price(){
return this.model.price
}
get name(){
return this.model.name
}
static totalPrice(data){
return data.reduce((t,c)=>{
return t+c.price
},0)
}
static createBatch(data){
return data.map(item => new Lesson(item))
}
static maxPrice(data){
data.sort((a,b)=>b.price - a.price)
return data[0]
}
}
let lessons = Lesson.createBatch(data)
console.log(Lesson.maxPrice(lessons).name)
console.log(Lesson.totalPrice(lessons))
</script>
</body>
</html>
类中使用访问器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class Request{
constructor(host){
this.data = {}
this.host = host
}
set host(url){
if(!/^https?:\/\//i.test(url)){
throw new Error("地址错误")
}
this.data.host = url
}
get host(){
return this.data["host"]
}
}
let hd = new Request("https://www.houdunren.com")
// hd.host = "hdcms.com"
// hd.setUrl("https://hdcms.com")
console.log(hd)
</script>
</body>
</html>
使用命名规则保护属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
//public
_url = "https://houdunren.com"
_site = "后盾人"
constructor(name){
this.name = name
}
set url(url){
if(!/^https?:/i.test(url))
{
throw new Error("非常网址")
}
this._url = url
}
}
let hd = new User("后盾人")
hd.name = "李四"
hd.url = "https://hdcms.com"
</script>
</body>
</html>
使用symbol定义protected属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const protecteds = Symbol()
class Common{
constructor(){
this[protecteds] = {}
this[protecteds].host = "https://houdunren.com"
}
set host(url){
if(!/^https?:/i.test(url))
{
throw new Error("非常网址")
}
this[protecteds].host = url
}
get host(){
return this[protecteds].host
}
}
class User extends Common{
constructor(name){
super() //子类的构造函数中调用父类的构造函数
this[protecteds].name = name
}
get name(){
return this[protecteds].name
}
}
let hd = new User("后盾人")
hd.host = "https://www.hdcms.com"
// console.log(hd[Symbol()].name)
</script>
</body>
</html>
使用WeakMap保护属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const protecteds = new WeakMap()
class Comment{
constructor(){
protecteds.set(this,{
host:"https://houdunren.com"
})
}
set host(url){
if(!/^https?:/i.test(url))
{
throw new Error("非常网址")
}
protecteds.set(this,{...protecteds.get(this),url})
}
get host(){
return protecteds.get(this)["host"]
}
}
class User extends Common{
constructor(name){
super()
this.name = name
}
set name(name){
protecteds.set(this,{...protecteds.get(this),name})
}
get name(){
return protecteds.get(this)["name"]
}
}
let hd = new User("后盾人")
// console.log(hd.host)
// let xj = new User("向军")
// xj.host = "https://www.hdcms.com"
// console.log(xj.host)
hd.name = "向军"
console.log(hd.name)
</script>
</body>
</html>
private私有属性使用
ES2022 引入了私有字段的语法,使用 #
符号来定义私有属性,这种方式更加简洁和直观
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
#host = "https://houdunren.com"
constructor(name){
this.name = name
}
set url(url){
if(!/^https?:/i.test(url))
{
throw new Error("非常网址")
}
this.host = url
}
}
let hd = new User("后盾人")
hd.host = "https://www.hdcms.com"
console.log(hd.name)
</script>
</body>
</html>
class属性继承原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function User(name){
this.name = name
}
function Admin(name){
User.call(this,name)
}
Admin.prototype = Object.create(User.prototype)
Admin.prototype.show = function(){}
let hd = new Admin("后盾人")
console.log(hd)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
constructor(name){
this.name = name
}
}
class Admin extends User{
constructor(name){
super(name)
}
}
let hd = new Admin("后盾人")
</script>
</body>
</html>
类的属性继承原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function User(){}
User.prototype.show = function(){
console.log("后盾人")
}
function Admin(){}
Admin.prototype = Object.create(User.prototype)
console.dir(Admin)
let hd = new Admin()
hd.show()
</script>
</body>
</html>
换种方法还是原型是底层
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
show(){
console.log("后盾人")
}
}
class Admin extends User{
constructor(name){
super()
this.name = name
}
}
let hd = new Admin("向军")
hd.show()
</script>
</body>
</html>
Super原理分析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
show(){
console.log("user.show")
}
}
class Admin extends User{
show(){
console.log("admin show")
}
}
let hd = {
name:"hd.name",
show(){
// console.log(this)
console.log("hd.show")
}
}
let xj = {
__proto__:hd,
name:"xj.name",
show(){
this.__proto__.show().call(this) //原型攀升
}
}
console.log(xj)
hd.show()
</script>
</body>
</html>
super()
实际上是调用了父类的构造函数
在子类的方法中,可以使用 super.method()
来调用父类中被重写的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
show(){
console.log(this.name)
}
}
class Admin extends User{
constructor(name){
super()
this.name = name
}
show(){
super.show()
}
}
let hd = new Admin("后盾人")
hd.show()
</script>
</body>
</html>
多继承中的super
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let commen = {
show(){
console.log("commen.show" + this.name)
}
}
let hd = {
__proto__:commen,
name:"hd.name",
show(){
super.show()
}
}
let xj = {
__proto__:hd,
name:"xj.name",
show(){
super.show()
}
}
xj.show()
</script>
</body>
</html>
子类constructor执行super
子类声明的constructor则必须要执行super
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class User{
constructor(name){
this.name = name
}
}
class Admin extends User{
constructor(...args)
{
super(...args)
this.name = "houdunren.com" //子类可以覆盖父类的
}
}
let hd = new Admin("后盾人")
console.log(hd)
// function User(name){
// this.name = name
// }
// function Admin(...args){
// User.apply(this,...args)
// }
// Admin.prototype = Object.create(User.prototype)
// let hd = new Admin("后盾人")
// console.log(hd)
</script>
</body>
</html>
使用super访问父类方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class Common{
sum(){
return this.data.reduce((t,c)=>t+c.price,0)
}
}
class Controller extends Common{}
class Lesson extends Controller{
constructor(data){
super()
this.data = data
}
info(){
return{
totalPrice:super.sum(),
data:this.data
}
}
}
let data = [
{name:"js",price:100},
{name:"mysql",price:212},
{name:"vue",price:98}
]
let hd = new Lesson(data)
console.log(hd.info())
</script>
</body>
</html>
重写父类方法
子类方法覆盖父类方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
class Common{
sum(){
return this.data.reduce((t,c)=>t+c.price,0)
}
getByKey(Key){
return this.data.filter(item=>item.name.includes(Key))
}
}
class Controller extends Common{}
class Lesson extends Controller{
constructor(data){
super()
this.data = data
}
info(){
return{
totalPrice:super.sum(),
data:this.data
}
}
getByKey(Key){
return super.getByKey(Key).map(item => item.name)
}
}
let data = [
{name:"js",price:100},
{name:"mysql",price:212},
{name:"vue",price:98}
]
let hd = new Lesson(data)
console.log(hd.getByKey("js"))
</script>
</body>
</html>
静态继承原理
静态方法的实现就是靠原型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// function User(){}
// User.site = "后盾人"
// User.show = function(){
// console.log("User.static.method")
// }
// console.log(User)
class User{
static site = "houdunren.com"
static show(){
console.log("user.static.show")
}
}
class Admin extends User{}
</script>
</body>
</html>