不错
类的内部的工作机制就是原型操作
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>