Javascript教程第十四章:类--简化面向对象开发

9 天前(已编辑)

Javascript教程第十四章:类--简化面向对象开发

Javascript教程第十四章:类--简化面向对象开发

类的内部操作实际上就是原型操作 类语法糖本质上就是上面提到的构造函数,constructor是函数的特殊值,方法会自动添加到构造函数的原型当中

一.类(简化面向对象开发)

类的内部操作实际上就是原型操作 类语法糖本质上就是上面提到的构造函数,constructor是函数的特殊值,方法会自动添加到构造函数的原型当中

1.class声明类的语法

class User{
    constructor(name){
        this.name = name;
    }
    getName(){
        return this.name;
    }
}

//在class语法当中添加的方法会默认添加到原型当中,并且设置为不可遍历,并且默认使用严格模式,所以函数中的this是默认为undefineed

2.class中的方法和静态方法

class User{
    show(){
        console.log("prototype.method")
    }
    static show(){
        console.log("__proto__.method")
    }
}s
User.show();            //默认添加至__proto__.method
new User().show();      //默认添加至prototype.method

3.静态属性之课程管理类

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
js const protect = Symbol(); class User{ _url = "https://houdunren.com" constructor(name){ this[protect] = {} } set url(newValue){ if(!/^https?:/i.test(newValue)){ throw new Error("错误网址") } this[protect].url = newValue; } get url(){ return this[protect].url; }

} 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;
        })
    }
}

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...