继承是原型的继承
<!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 f = {}console.log(f.__proto__)function User() {User.prototype.name = function () {console.log("user.name")}}function Admin() { }// Admin.prototype.__proto__ = User.prototypeAdmin.prototype = Object.create(User.prototype)Admin.prototype.role = function () {console.log("admin.role")}function Member() { }Member.prototype = Object.create(User.prototype)Member.prototype.role = function () {console.log("member.role")}let a = new Admin()a.role()</script>
</body></html>
两种方式都可以实现继承
禁止constructor被遍历
有的时候不希望constructor被遍历
<!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 Admin(){Admin.prototype = Object.create(User.prototype)console.log(Object.getOwnPropertyDescriptor(Admin.prototype))Object.defineProperty(Admin.prototype,'construct',{value:Admin})Admin.prototype.role = function(){console.log("admin.role")}let a = new Admin()for(const key in a){console.log(key)}}</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("user.name")}}User.prototype.site = function(){return "后盾人"}function Admin(){}Admin.prototype = Object.create(User.prototype)Admin.prototype.constructor = AdminAdmin.prototype.show = function(){console.log(User.prototype.site() + "admin.show")}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>function User(){}User.prototype.show = function(){console.log(this.description())}function Admin(){}Admin.prototype = Object.create(User.prototype)Admin.prototype.description = function(){return "管理员在此"}function Member(){}Member.prototype = Object.create(User.prototype)Member.prototype.description = function(){return "我是会员"}function Enterprise(){}Enterprise.prototype = Object.create(User.prototype)Enterprise.prototype.description = function(){return "企业账户"}for(const obj of [new Admin(),new Member(),new Enterprise()]){obj.show()//假如没有多态if(obj instanceof Admin){console.log(obj.showAdmin())}}</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>let hd = {name: "后盾人",view() {console.log(this.name)}}hd.view()function User(name, age) {this.name = namethis.age = age}User.prototype.show = function () {console.log(this.name, this.age)}function Admin(...args) {User.apply(this, args)}Admin.prototype = Object.create(User.prototype)let xj = new Admin("向军", 18)xj.show()function Member(...args) {User.apply(this, args)}Member.prototype = Object.create(User.prototype)let lisi = new Member("李四", 19)lisi.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>function extend(sub,sup){sub.prototype = Object.create(sup.prototype)Object.defineProperty(sub.prototype,"constructor",{value:sub,enumerable:false})}function User(name,age){this.name = namethis.age = age}User.prototype.show = function(){console.log(this.name,this.age)}function Admin(...args){User.apply(this,args)}extend(Admin,User)let admin = new Admin('向军',19)admin.show()function Member(...args){User.apply(this,args)}extend(Member,User)let member = new Member('李四',23)member.show()// Member.prototype = Object.create(User.prototype)// Object.defineProperty(Member.prototype,"constructor",{// value:Member,// enumerable:false// })</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(name,age){this.name = namethis.age = age}User.prototype.show = function(){console.log(this.name,this.age)}function admin(name,age){const instance = Object.create(User.prototype)User.call(instance,name,age)instance.role = function(){console.log("role")}return instance}let hd = admin("向军",19)hd.show()hd.role()// let admin = new Admin('向军',19)// admin.show()// function Member(...args){// User.apply(this,args)// }// extend(Member,User)// let member = new Member('李四',23)// member.show()// Member.prototype = Object.create(User.prototype)// Object.defineProperty(Member.prototype,"constructor",{// value:Member,// enumerable:false// })</script>
</body>
</html>
mixin实现多继承
// 定义一些 mixin 对象
const canEat = {eat() {console.log('I can eat.');}
};const canWalk = {walk() {console.log('I can walk.');}
};const canSwim = {swim() {console.log('I can swim.');}
};// 定义一个基础类
class Person {}// 定义一个混入函数
function mixin(target, ...sources) {Object.assign(target.prototype, ...sources);
}// 进行混入操作
mixin(Person, canEat, canWalk, canSwim);// 创建 Person 实例
const person = new Person();// 调用混入的方法
person.eat();
person.walk();
person.swim();
使用工厂函数混入:
// 定义一些 mixin 函数
function canFly() {return {fly() {console.log('I can fly.');}};
}function canClimb() {return {climb() {console.log('I can climb.');}};
}// 定义一个基础类
class Animal {}// 定义一个工厂函数进行混入
function createMixinAnimal(...mixins) {class MixedAnimal extends Animal {}mixins.forEach(mixin => {Object.assign(MixedAnimal.prototype, mixin());});return MixedAnimal;
}// 创建一个混入了 canFly 和 canClimb 的新类
const FlyingClimbingAnimal = createMixinAnimal(canFly, canClimb);// 创建实例
const animal = new FlyingClimbingAnimal();// 调用混入的方法
animal.fly();
animal.climb();
mixin的内部继承与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>function extend(sub,sup){sub.prototype = Object.create(sup.prototype)Object.defineProperty(sub.prototype,"constructor",{value:sub,enumerable:false})} const Address = {getAddress(){console.log("获取收货地址")}}const Request = {ajax(){return "请求后台"}}const Credit = {__proto__:Request,total(){console.log(super.ajax()+"积分统计")}} function User(name,age){this.name = name this.age = age}User.prototype.show = function(){console.log(this.name,this.age)}function Admin(name,age){User.call(this,name,age)}extend(Admin,User)Admin.prototype = Object.assign(Admin.prototype,Request,Credit)let admin = new Admin("向军",19)admin.show()admin.ajax()admin.total()function Member(name,age){User.call(this,name,age)}extend(Member,User)// Member.prototype = Object.assign(Admin.prototype,Request,Credit)// let lisi = new Member("李四",22)// lisi.getAddress()</script>
</body>
</html>
Tab选项卡显示效果基类开发
<!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><main class="tab2"><nav><a href="javascript:;">后盾人</a><a href="javascript:;">hdcms</a></nav><section>1</section><section>2</section></main><script>function extend(sub,sup){sub.prototype = Object.create(sup.prototype)sub.prototype.constructor = sub}function Animation(){}Animation.prototype.show = function(){this.style.display = "block"}Animation.prototype.hide = function(){this.style.display = "none"}Animation.prototype.background = function(color){this.style.backgroundColor = color}// let tab = document.querySelector('.tab')// Animation.prototype.background.call(tab,"red")</script>
</body>
</html>
好用的TAB业务管理类
<!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><main class="tab1"><nav><a href="javascript:;">后盾人</a><a href="javascript:;">hdcms</a></nav><section>1</section><section>2</section></main><main class="tab2"><nav><a href="javascript:;">后盾人</a><a href="javascript:;">hdcms</a></nav><section>1</section><section>2</section></main><script>function extend(sub,sup){sub.prototype = Object.create(sup.prototype)sub.prototype.constructor = sub}function Animation(){}Animation.prototype.show = function(){this.style.display = "block"}Animation.prototype.hide = function(){this.style.display = "none"}Animation.prototype.background = function(color){this.style.backgroundColor = color}// let tab = document.querySelector('.tab')// Animation.prototype.background.call(tab,"red")function Tab(el){ this.tab = document.querySelector(el)this.links = this.tab.querySelectorAll('a')this.sections = this.tab.querySelectorAll('section')}extend(Tab,Animation)Tab.prototype.run = function(){this.bindEvent()this.reset()this.action(0)}Tab.prototype.bindEvent = function(){this.links.forEach((el,i) => {el.addEventListener("click",()=>{this.reset()this.action(i)}) });}Tab.prototype.action =function(i){this.background.call(this.links[i],"#e67e22")this.show.call(this.sections[i])}Tab.prototype.reset =function(){this.links.forEach((el,i)=>{this.background.call(this.links[i],"#95a5a6")this.hide.call(this.sections[i])})}new Tab('.tab2').run()</script>
</body>
</html>
也可以通过设置默认参数来进行更多的设置,让自由度更高