面向对象和设计模式

类的声明

以下以 ES5 为例,ES6 引入 class 关键字,可以像其他语言一样直接使用 class 声明类

我们可以使用 function 关键字,类似于声明一个函数一样,声明一个类。

function Book(name,writer,price){
    this.name=name;
    this.writer=writer;
    this.price=price;
}

注意,根据命名规范,如果 function 声明的是类,类名首字母需要大写。

声明好了类,我们就可以使用 new 关键字来生成一个对象

var book = new Book("book1","Tom","59.9")

Ï当然,我们也可以给 Book 类添加成员方法,给 类添加成员方法 一般有两种常用方法

使用 this 赋值成员方法

我们可以像声明成员变量一样声明类的成员方法,毕竟 js 中函数是一等公民,可以当变量一样使用

function Book(name,writer,price){
    this.name=name;
    this.writer=writer;
    this.price=price;
    // 这里需要注意保留 Book 函数域内的 this
    var that = this;
    // function 中的 this 是指向自身的,所以需要使用 that
    this.getRMB = function (){
        return that.price+"元";
    }
}

var book = new Book("book1","Tom","59.9")
var book2 = new Book("book2","jack","29.9")

// 调用成员方法
book.getRMB()

console.log(book.getRMB == book2.getRMB) //false,每个对象的 getRMB 都是独立的函数

使用 prototype 声明成员方法

我们可以通过给类的 constructor 添加 prototype ,js 会自动给其生成的对象添加 __proto__ 属性,形成原型链. 从而实现对象共享成员方法

function BookP(name,writer,price){
    this.name=name;
    this.writer=writer;
    this.price=price;
}

// 设置 BookP 的 prototype 属性
BookP.prototype.getRMB = function(){
    return this.price+"元";
}


var bookp = new BookP("book1","Tom","59.9")
var bookp2 =  new BookP("book2","jack","29.9")

// 调用成员方法
bookp.getRMB()

console.log(bookp.getRMB == bookp2.getRMB) // true, 所有对象共用一个 getRMB

这个方法所有对象共享同一成员函数,效率更高,建议使用

代码封装

学会了类的概念,我们就可以使用类来封装模块,使得我们的代码可重用,同时又屏蔽了代码的复杂性。

下面就以 返回顶部 为例,进行代码封装

目的

我们在外部可以使用如下代码,即可在页面中添加 返回顶部 按钮

var ele = $(".back-top")
new BackTop(ele);

实现

function BackTop($node){
    var timer;
    $node.on("click",function(){
        window.scrollTo(0,0);
    })
    window.onscroll = function () {
        console.log("onscroll")

        // 防止事件过多
        clearTimeout(timer)
        timer = setTimeout(function () {
            var windowH = $(window).height();
            var scrollTop = $(window).scrollTop();
            if(scrollTop > windowH *0.5){
                $node.addClass("show")
            }
            if(scrollTop < windowH *0.5){
                $node.removeClass("show")
            }
        }, 50)
    }
}

我们可以把复杂的逻辑包装在 BackTop这个类里

完整代码可以参看这里

常用设计模式

工厂模式

我们来看一个简单的例子:

var employee1 = new Object();
employee1.position = "Front end engineer";
employee1.tool = "I love vscode.";
employee1.introduction = function () {
    console.log("I am a " + this.position + ", and " + this.tool);
}
var employee2 = new Object();
employee2.position = "UI designer";
employee2.tool = "I love photoshop.";
employee2.introduction = function () {
    console.log("I am a " + this.position + ", and " + this.tool);
}
employee1.introduction(); // I am a Front end engineer, and I love vscode.
employee2.introduction(); // I am a UI designer, and I love photoshop.

在上边这个例子中,我们定义了两个employee,一个是Front End Engineer,另一个是UI designer,他们都有position属性和tool属性,也都有introduction方法。如果我们需要创建很多个类似employee的对象呢,那我们就需要重复很多类似的代码。接下来,我们做一些简单的修改:

function Employee(type) {
    var employee;
    if (type == "programmer") {
        employee = new Programmer();
    } else if (type == "designer") {
        employee = new Designer();
    }
    employee.introduction = function () {
        console.log("I am a " + this.position + ", and " + this.tool);
    }
    return employee;

}

function Programmer() {
    this.position = "Front end engineer";
    this.tool = "I love vscode.";
}
function Designer() {
    this.position = "UI designer";
    this.tool = "I love photoshop.";
}

var employee1 = Employee("programmer");
employee1.introduction();//I am a Front end engineer, and I love vscode.
var employee2 = Employee("designer");
employee2.introduction();//I am a UI designer, and I love photoshop.

单例模式

单例模式提供了一种将代码组织为一个逻辑单元的手段,这个逻辑单元中的代码可以通过单一变量进行访问。 优点是:

  • 可以用来划分命名空间,减少全局变量的数量。
  • 使用单体模式可以使代码组织的更为一致,使代码容易阅读和维护。
  • 可以被实例化,且实例化一次。
function Singleton(name){
    this.name = name;
};
Singleton.prototype.getName = function(){
    return this.name;
}
// 获取实例对象
Singleton.getInstance = function() {
    if(!this.instance) {
        this.instance = new Singleton();
    }
    return this.instance;
}
// 测试单体模式的实例
var a = Singleton.getInstance();
var b = Singleton.getInstance();

console.log(a == b) // true,为同一个对象

在实际使用中,如遇模式对话框等场景,我可以考虑使用单例模式

其他设计模式

其实还有很多设计模式,如

  • 模块模式
  • 代理模式
  • 职责链模式
  • 命令模式
  • 模板方法模式
  • 策略模式
  • 订阅模式
  • 中介者模式

具体可以参看这里

results matching ""

    No results matching ""