Javascript教程第十四章:类--简化面向对象开发
Javascript教程第十四章:类--简化面向对象开发
类的内部操作实际上就是原型操作 类语法糖本质上就是上面提到的构造函数,constructor是函数的特殊值,方法会自动添加到构造函数的原型当中
一.类(简化面向对象开发)
类的内部操作实际上就是原型操作 类语法糖本质上就是上面提到的构造函数,constructor是函数的特殊值,方法会自动添加到构造函数的原型当中
1.class声明类的语法
class User{
    constructor(name){
        this.name = name;
    }
    getName(){
        return this.name;
    }
}
//在class语法当中添加的方法会默认添加到原型当中,并且设置为不可遍历,并且默认使用严格模式,所以函数中的this是默认为undefineed2.class中的方法和静态方法
class User{
    show(){
        console.log("prototype.method")
    }
    static show(){
        console.log("__proto__.method")
    }
}s
User.show();            //默认添加至__proto__.method
new User().show();      //默认添加至prototype.method3.静态属性之课程管理类
let data = [
    {name:"js",price:188},
    {name:"css",price:88},
    {name:"java",price:288},
]
class Lessons{
    constructor(data){
        this.model = data;
    }
    price(){
        return this.model.price;
    }
    name(){
        return this.model.name;
    }
    //批量处理使用static
    static createBatch(data){
        return data.map((item) => new Lessons(item))
    }
    //获取最高价格,对所有数据进行操作,使用静态方法
    static maxPrice(data){
        return data.sort((a,b) => (b.price - a.price))[0].price;
    }
}4.class中使用命名规则保护属性的方法
1.规范一:
在类内部以_开头的通常为私有属性,且表示只能通过对象方法访问的属性,开发者应该遵循而不应该随意修改 ```js class User{ _url = "https://houdunren.com" constructor(name){ this.name = name; } set url(newValue){
    //正则验证网址
    if(!/^https?:/i.test(newValue)){
        throw new Error("错误网址")
    }
    this._url = newValue;
}
get url(){
    return this._url;
}} let hd = new User("hd") // hd.url = "sss" //报错:错误网址 hd.url = "https://www.baidu.com" console.log(hd.url); //https://www.baidu.com
上面我们通过set和get属性访问器来对私有属性进行了保护,但是我们仍然可以人为的修改_url,下面我们使用Symbol来定义protected
(1).使用Symbol保护属性
> 这种方式可以在本类及其子类中调用,我们将Symbol作为对象的属性名,调用set在其中压入需要被保护的值,这样我们外部就无法通过属性名称来直接获取到值,只能通过get,当然我们也可以给外部开放API} let hd = new User("hd") // hd.url = "sss" //报错:错误网址 hd.url = "https://www.baidu.com" console.log(hd.url); //https://www.baidu. ```
(2).使用WeakMap保护属性
接下来我们通过WeakMap的不可迭代性来保护属性
js
const host = new WeakMap();
class User{
    _url = "https://houdunren.com"
    constructor(name){
        this.name = name;
        host.set(this,"houdunren")
    }
    set url(newValue){
        if(!/^https?:/i.test(newValue)){
            throw new Error("错误网址")
        }
        host.set(this,newValue)
    }
    get url(){
        return host.get(this);
    }
}
2.规范二:private私有属性使用
只能在本类中使用 ```js class User{
#host = "www.houdunren.com"
constructor(name){
    this.name = name;
    this.#check(name)
}
set host(url){
    this.#host = url
}
//注意,方法定义私有的时候必须定义成变量形式
#check = ()=>{
    if(this.name.length < 5){
        throw new Error ("名字不能小于五位") 
    }  
    return true;
}} ```
5.super在多重继承中的魅力
super只是进行原型攀升,this一直指向调用的对象,super调用上级原型的方法时,必须定义为show(),而不能定义成函数格式show:function(){}
6.使用类封装类似Jquery的隐藏显示效果
class Animation{
    constructor(el){
        this.el = el;
        this.isShow = true;
        this.defaultHeight = this.height;
    }
    set height(height){
        this.el.style.height = height + 'px';
    }
    get height(){
        return window.getComputedStyle(this.el).height.slice(0,-2)*1
    }
    hide(callback){
        this.isShow = false;
        let id = setInterval(() => { 
            if(this.height <= 0){
                clearInterval(id);
                callback && callback();
                return;
            }
            this.height = this.height - 1;
        }, 10);
    }
    show(callback){
        this.isShow = true;
        let id = setInterval(() => {
            if(this.height >= this.defaultHeight){
                clearInterval(id);
                callback && callback();
                return;
            }
            this.height = this.height + 1;
        }, 10);
    }
}7.滑动效果和面板类动画
class Slide{
    constructor(el){
        this.el = document.querySelector(el);
        this.links = this.el.querySelectorAll("dt");
        this.panels = [...this.el.querySelectorAll("dd")].map(
            item => new Panel(item)
        );
        console.log(this.panels);
        
        this.bind();
    }
    //绑定事件
    bind(){
        this.links.forEach((linksItem,index) => {
            linksItem.addEventListener("click",()=>{
                this.action(index);
            })
        });
    }
    //点击事件动作
    action(index){
        //隐藏后执行回调函数进行显示,防止动画异步
        Panel.hideAll(Panel.filter(this.panels,index),()=>{
            this.panels[index].show()
        });
    }
}
//面板类
class Panel extends Animation{
    static num = 0;
    //隐藏多个面板,使用静态方法
    static hideAll(items,callback){
        //当有动画执行的时候不做处理,防止动画异步
        if(Panel.num>0) return;
        items.forEach(item => {
            Panel.num++;
            item.hide(()=>{
                Panel.num--;
            });
        })
        callback && callback()
    }
    //过滤点击面板
    static filter(items,index){
        return items.filter((item,i) => {
            return i != index;
        })
    }
}