K0II / JavaScript

Learning Logs
0 stars 0 forks source link

JavaScript设计模式 - learning logs #7

Open K0II opened 8 years ago

K0II commented 8 years ago

// 一个类
var checkObject = function() {
    this.checkName = function() {};
    this.checkEmail = function() {};
    this.checkPassword = function() {};
};

var a = new checkObject();
a.checkName();

所有通过this定义的方法放在了函数内部,所以每一次通过new关键字创建新对象时候,新创建的对象都会对类的this上的属性进行复制。所以这些新创建的对象都会有自己的一套方法,造成的消耗很奢侈。

var checkObject = function() {};

checkObject.prototype = {
    checkName: function() {
        // 验证姓名
        return this;
    },
    checkEmail: function() {
        // 验证邮箱
        return this;
    },
    checkPassword: function() {
        // 验证密码
        return this;
    }
}

var a = new checkObject();
a.checkName().checkEmail().checkPassword();

this指向当前对象(a)

有一些方法没有返回值,例如,一些设置或修改对象的某个状态却不返回任何值的方法。 让这些方法返回this而不是undefined(没有return默认返回undefined),就可以启动级联(Cascade)。 让每一方法都返回该对象,所以每次调用的结果可以被下一次调用所用。 一个接口没必要一次做太多事

var Book = function (bookId, bookName, price) {
    var num = 1;  //  私有属性
    function checkId () {};  //  私有方法

    // 对象共有属性
    this.bookId = bookId;

    // 对象共有方法
    this.copy = function () {};
    // 特权方法
    this.getName = function() {};
    this.getPrice = function() {};
    this.setName = function() {};
    this.setPrice = function() {};

    // 构造器
    this.setName(bookName);
    this.setPrice(price);
};

var aBook = new Book(01,'YOU DON`T KNOW JS',49);
K0II commented 8 years ago

函数祖先添加方法

Function.prototype.method = function(name,func) {
    // 没有这个方法的话添加(避免重名)
    if (!Function.prototype[name]) {
        this.prototype[name] = func;
    }
    return this;
}

上面的comment可以这样实现

var checkObject = function() {};

checkObject.method('checkName', function() {
    // 验证姓名
    return this;
 }).method('checkEmail', function() {
    // 验证邮箱
    return this;
 }).method('checkPassword', function() {
    // 验证密码
    return this;
});

var a = new checkObject();
a.checkName().checkEmail().checkPassword();
K0II commented 8 years ago

面向对象 - 封装

var Book = function (bookId, bookName, price) {
    this.bookId = bookId;
    this.bookName = bookName;
    this.price = price;
};

Book.method('display', function() {
    console.log(this.bookId + ' - ' + this.bookName + ' - ' + this.price);
    return this;
});

var aBook = new Book(01,'YOU DON`T KNOW JS',49);

aBook.display();

属性与方法封装

声明在函数内部的变量以及方法在外界是访问不到的,通过此特性可创建类的私有变量私有方法

在函数内部通过this创建的属性和方法,在用new创建对象时,每个对象都能拥有一份,并且在外部可以访问到,因此通过this创建的属性可看作是对象的共有属性和方法;

而通过this创建的方法,不但可以访问到这些对象的共有属性和方法,而且还能访问到构造类或被创建的对象的自身的私有属性和方法。这些方法特权很大,被称为特权方法

var Book = function (bookId, bookName, price) {
    var num = 1;  //  私有属性
    function checkId () {};  //  私有方法

    // 对象共有属性
    this.bookId = bookId;

    // 对象共有方法
    this.copy = function () {};
    // 特权方法
    this.getName = function() {};
    this.getPrice = function() {};
    this.setName = function() {};
    this.setPrice = function() {};

    // 构造器
    this.setName(bookName);
    this.setPrice(price);
};

var aBook = new Book(01,'YOU DON`T KNOW JS',49);

将类的静态变量通过闭包实现

var Book = (function() {
    // 静态私有变量
    var bookNum = 0;

    // 静态私有方法
    function checkBook () {};

    // 构造函数
    function _book (bookId, bookName, price) {
        // 私有变量
        var bookName;
        var price;

        // 私有方法
        function checkId() {}

        // 对象共有属性
        this.bookId = bookId;

        // 对象共有方法
        this.copy = function () {};
        // 特权方法
        this.getName = function() {};
        this.getPrice = function() {};
        this.setName = function() {};
        this.setPrice = function() {};

        // 更改静态私有变量
        bookNum ++;  //  每用 new调用一次 Book, bookNum增加1

        if (bookNum>100) {
            throw new Error('我们仅出版100本书');
        }

        // 构造器
        this.setName(bookName);
        this.setPrice(price);
    };
    _book.prototype = {
        isJSBook: false,
        display: function() {
            console.log(this.bookId);
        }
    }
    return _book;
})();

Book;  //  _book(bookId, bookName, price)

var aBook = new Book(01,'YOU DON`T KNOW JS',49);
aBook;
// bookId 1
// isJSBook false
// copy function() 
// display function() 
// getName function() 
// getPrice function() 
// setName function()
// setPrice function()
// __proto__ Object { isJSBook=false,  display=function()}
K0II commented 8 years ago

为什么要用闭包实现呢?

var Book = function() {
    // 静态私有变量
    var bookNum = 0;

    // 静态私有方法
    function checkBook () {};

    // 构造函数
    function _book (bookId, bookName, price) {
        // 私有变量
        var bookName;
        var price;

        // 私有方法
        function checkId() {}

        // 对象共有属性
        this.bookId = bookId;

        // 对象共有方法
        this.copy = function () {};
        // 特权方法
        this.getName = function() {};
        this.getPrice = function() {};
        this.setName = function() {};
        this.setPrice = function() {};

        // 更改静态私有变量
        bookNum ++;  //  每用 new调用一次 Book, bookNum增加1
        console.log(bookNum);

        if (bookNum>100) {
            throw new Error('我们仅出版100本书');
        }

        // 构造器
        this.setName(bookName);
        this.setPrice(price);
    };
    _book.prototype = {
        isJSBook: false,
        display: function() {
            console.log(this.bookId);
        }
    }
    return _book;
};

Book;  //   function()

var aBook = new Book(01,'YOU DON`T KNOW JS',49);
aBook;  //  _book(bookId, bookName, price)
aBook();  //  1

var bBook = new Book(01,'YOU DON`T KNOW JS',49);
bBook;  //  _book(bookId, bookName, price)
bBook();  //  1

new aBook(02,'22',22);  // 2
new aBook(02,'22',22);  // 3
new aBook(02,'22',22);  // 4
new aBook(02,'22',22);  // 5
new aBook(02,'22',22);  // 6
K0II commented 8 years ago

继承

function Father() {
    this.name = 'Dad';
    this.arr = [1,2,3];
}
Father.method('showName', function() {
    return this.name + ' From Father';
});

function Son() {
    this.name = 'Son';
}
Son.prototype = new Father();
Son.method('showName', function() {
    return this.name + ' From Son';
});

var foo = new Son();
foo.name;    //  Son
foo.showName();    //  Son From Son

foo.arr.push(4);

var bar =  new Son();
bar.arr;    //  [1, 2, 3, 4]
K0II commented 8 years ago

上面说的类都不是真的类