第二章-寫的都是看到的-面向對象編程(javascript設計模式-張銘容)

封裝類javascript

var Book = function (id, bookname, price) { this.id = id; this.bookname = bookname; this.price = price;};

類的原型css

Book.prototype = { display: function () {
 console.log("展現這本書");
 }};

constructor 屬性返回對建立此對象的數組函數的引用html

var book = new Book(10, 'javascript設計模式', 50);console.dir(Book);
console.dir(Book.prototype.constructor);//Book Object
console.log(book);

面向對象思想 私有屬性 私有方法 共有屬性 保護方法 ...java

//私有屬性與私有方法,特權方法,對象共有屬性和對象共有方法,構造器
var BookTwo = function (id, name, price) { //私有屬性 var num = 1; //私有方法 function checkId() {
 console.log(this.id);
 }
 //特權方法 this.getName = function () { return this.name;
 }; this.getPrice = function () { return this.price; }; this.setName = function (name) { this.name = name; }; this.setPrice = function (price) { this.price = price; }; //對象公有屬性 this.id = id; //對象公有方法 this.copy = function () { console.log('copy');
 }; //構造器 this.setName(name); this.setPrice(price);};
//類靜態公有屬性(對象不能訪問)
BookTwo.isChinese = true;//類靜態公有方法(對象不能訪問)
BookTwo.resetTime = function () { console.log('new Tiem');
};
BookTwo.prototype = { //公有屬性 isJSBook: false,
 //公有方法 display: function () {
 console.log("顯示");
 }};
var booktwo = new BookTwo(11, 'javascript設計模式', 50);
console.log(booktwo);
console.log(booktwo.num);//undefined
console.log(booktwo.isJSBook);//false
booktwo.display();//顯示
console.log(booktwo.id);//11
console.log(booktwo.isChinese);//undefined
//類的靜態公有屬性能夠經過類的自身訪問
console.log(BookTwo.isChinese);//true
BookTwo.resetTime();//new Time

類的靜態變量 經過閉包來實現ajax

//利用閉包來實現
var BookThree = (function () { //靜態私有變量 var bookNum = 0; //靜態私有方法 function checkBook(name) {
 console.log(name);
 }
 //構造函數 function _book(newId, newName, newPrice) {
 //私有變量 var name, price; //私有方法 function checkID(id) {
 }
 //特權方法 this.getName = function () { return this.name;
 }; this.getPrice = function () { return this.price; }; this.setName = function (name) { this.name = name; }; this.setPrice = function (price) { this.price = price; }; //公有屬性 this.id = newId; //公有方法 this.copy = function () { }; bookNum++; if (bookNum > 100) { throw new Error('咱們僅出版100本書');
 } //構造器 this.setName(newName); this.setPrice(newPrice); }
 return _book;
})();
var bookThree = new BookThree(11, 'javascript設計模式', 50);
console.log(bookThree);

建立對象的安全模式-去除 new 也可成功事例化對象設計模式

var BookFour = function (id, name, price) { this.id = id; this.name = name; this.price = price;};
var bookFour = BookTwo(12, 'javascript設計模式', 50);console.log(bookFour);//undefined
console.log(window.id);//12
console.log(window.name);//javascript設計模式
console.log(window.price);//50
bookFour = new BookTwo(13, 'javascript設計模式', 50);console.log(bookFour);
//圖書安全類
/*
 * instanceof 運算符用來判斷一個構造函數的prototype屬性所指向的對象是否存在另一個要檢測對象的原型鏈上 * */var BookFive = function (id, name, price) { //判斷執行過程當中的this是不是當前對象(若是是說明是new建立的) if (this instanceof BookFive) {
 this.id = id; this.name = name; this.price = price; } else {//從新建立這個對象 return new BookFive(id, name, price);
 }};
//都能成功建立
var bookFive = BookFive(14, 'javascript設計模式', 50);
console.log(bookFive);
bookFive = new BookFive(15, 'javascript設計模式', 50);
console.log(bookFive);

繼承

類式繼承 - 關鍵:SubClass.prototype = new SuperClass();數組

//聲明父類
function SuperClass() {
 this.superValue = true;}
//爲父類添加共有方法
SuperClass.prototype.getSuperValue = function () { return this.superValue;
};
//聲明子類
function SubClass() {
 this.subValue = false;}
//繼承父類
SubClass.prototype = new SuperClass();
//爲子類添加共有方法
SubClass.prototype.getSubValue = function () { return this.subValue;
};
var instance = new SubClass();
console.log(instance.getSuperValue());
console.log(instance.getSubValue());
/*
 * instance 判斷對象和類之間的繼承關係 實例-》類 * * 是判斷 實例 與 類 的繼承關係 * */console.log(instance instanceof SuperClass);//true
console.log(instance instanceof SubClass);//true
console.log(SubClass instanceof SuperClass);//false
console.log(SubClass.prototype instanceof SuperClass);//true
console.log(instance instanceof Object);//true

類式的缺點緩存

  • 1.因爲子類經過其原型prototype對父類實例化,繼承了父類。因此父類中
  • 公有的屬性要是引用類型,就會在子類中被全部實例共用,所以一個子類的
  • 實例更改字類原型從父類構造函數中繼承來的共有屬性就會直接影響到其餘子類
  • 2.因爲子類的實現的繼承是靠其原型prototype對父類的實例化實現的,因
  • 此在建立父類的時候,是沒法向父類傳遞參數的,於是在實例化父類的時候
  • 也沒法對父類構造函數類的屬性進行初始化
function SuperClassTwo() {
 this.books = ['Javascript', 'html', 'css'];}
function SubClassTwo() {
}
SubClassTwo.prototype = new SuperClassTwo();
var instance1 = new SubClassTwo();
var instance2 = new SubClassTwo();
console.log("類式的缺點");
console.log(instance1.books);//["Javascript", "html", "css"]
instance1.books.push('設計模式');
console.log(instance2.books);//["Javascript", "html", "css", "設計模式"]

總結:在修改instance1的時候instance2也被修改了這樣會形成程序的錯誤安全

  • 爲了解決這些產生了
  • 建立即繼承-構造函數繼承
    • 關鍵:SuperClassThree.call(this,id)
//構造函數式繼承
//聲明父類
function SuperClassThree(id) {
 //引用類型共有屬性 this.books = ['Javascript', 'html', 'css']; //值類型共有屬性 this.id = id;}
//父類聲明原型方法
SuperClassThree.prototype.showBooks = function () { console.log(this.books);
};
//聲明子類
function SubClassThree(id) {
 //繼承父類 SuperClassThree.call(this, id);
}
//建立第一個子類的實例
var instance3 = new SubClassThree(10);
//建立第一個子類的實例
var instance4 = new SubClassThree(11);
instance3.books.push("設計模式");
console.log(instance3.books);//["Javascript", "html", "css", "設計模式"]
console.log(instance3.id);//10
console.log(instance4.books);//["Javascript", "html", "css"]
console.log(instance4.id);//11
  • 總結:改正了類式繼承的缺點,但仍是有缺點,就是每一個實例都會單獨實例化一份
  • 父類的共用方法,這就違背了代碼複用的原則,爲了綜合這兩種繼承的優勢,後來
  • 有了----組合式繼承

將優勢爲我所用--組合繼承閉包

//組合繼承
//聲明父類
function SuperClassFour(name) {
 //值類型共有屬性 this.name = name; //引用類型共有屬性 this.books = ['html', 'css', 'Javascript']}
//父類原型共有方法
SuperClassFour.prototype.getName = function () { console.log(this.name);
};
//聲明子類
function SubClassFour(name, time) {
 //構造函數式繼承父類name屬性 SuperClassFour.call(this, name);
 //子類中新增共有屬性 this.time = time;}
//類式繼承 子類原型繼承父類實例
SubClassFour.prototype = new SuperClassFour();
//子類原型方法
SubClassFour.prototype.getTime = function () { console.log(this.time);
};
console.log('將優勢爲我所用--組合繼承');
var instance5 = new SubClassFour('js book', 2014);
console.log(instance5);
instance5.books.push('設計模式');
console.log(instance5.books);
instance5.getName();
instance5.getTime();
var instance6 = new SubClassFour('css book', 2013);
console.log(instance6.books);
instance6.getName();
instance6.getTime();
  • 缺點:父類的構造函數執行了兩遍
  • 潔淨的繼承者-原型式繼承
  • 藉助原型 prototype 能夠根據已有的對象建立一個新的對象,
  • 同時沒必要建立新的自定義對象類型

    function inheritObject(o) {
    //聲明一個過濾函數對象 function F() {
    }
    //過濾對象的原型繼承父對象 F.prototype = o; //返回過渡對象的一個實例,改實例的原型繼承了父隊象 return new F();
    }
    var book5 = { name: 'js book',
    alikeBook: ['css book', 'html book']
    };
    var newBook = inheritObject(book5);
    newBook.name = 'ajax book';newBook.alikeBook.push('xml book');
    var otherBook = inheritObject(book5);
    otherBook.name = 'flash book';otherBook.alikeBook.push('as book');
    console.log(newBook.name); //ajax book
    console.log(newBook.alikeBook);//["css book", "html book", "xml book", "as book"]
    console.log(otherBook.name);//flash book
    console.log(otherBook.alikeBook);// ["css book", "html book", "xml book", "as book"]
    console.log(book5.name);//js book
    console.log(book5.alikeBook);//["css book", "html book", "xml book", "as book"]

如虎添翼--寄生式繼承

//寄生式繼承
//聲明基對象
var book6 = { name: 'js book',
 alikeBook: ['css book', 'html book']
};
//原型式繼承
function inheritObjectTwo(o) {
 //聲明一個過濾函數對象 function F() {
 }
 //過濾對象的原型繼承父對象 F.prototype = o; //返回過渡對象的一個實例,改實例的原型繼承了父隊象 return new F();
}
function createBook(obj) {
 console.log(obj);
 //經過原型繼承方式建立新對象 var o = inheritObjectTwo(obj);
 console.log(o.name);
 //拓展新對象 o.getName = function () { console.log(this.name);
 }; //返回拓展後的新對象 return o;}
var book7 = createBook(book6);
console.log(book7.getName);

終極繼承者

/*
 * 寄生式繼承 繼承原型 * 傳遞參數 subClass 子類 * 傳遞參數 superClass 父類 * constructor 屬性返回對建立此對象的數組函數的引用。 * */function inheritPrototype(subClass, superClass) {
 //複製一份父類的原型副本保存在變量中 var p = inheritObject(superClass.prototype);
 //修正由於重寫子類原型致使子類的constructor屬性被修改 p.constructor = subClass; //設置子類的原型 subClass.prototype = p;}
//定義父類
function ParentClass(name) {
 this.name = name; this.colors = ['red', 'blue', 'green']}
//定義父類原型方法
ParentClass.prototype.getName = function () { console.log(this.name);
};
//定義子類
function ChildClass(name, time) {
 //構造函數式繼承 ParentClass.call(this, name);
 //子類新增屬性 this.time = time;}
//寄生式繼承父類原型
inheritPrototype(ChildClass, ParentClass);
//子類新增原型方法
ChildClass.prototype.getTime = function () { console.log(this.time);
};
//建立兩個測試方法
var test1 = new ChildClass('js book', 2014);
var test2 = new ChildClass('css book', 2013);
test1.colors.push('black');
console.log(test1.colors);//["red", "blue", "green", "black"]
console.log(test2.colors);//["red", "blue", "green"]
test2.getName();//css book
test2.getTime();//2013

老師不止一位--多繼承

// 單繼承 屬性複製
var extend = function (target, source) { //遍歷原對象中的屬性 for (var property in source) { target[property] = source[property]; } //返回目標對象 return target;};
//多繼承 屬性複製
var mix = function () { var i = 1,//從第二個參數起爲被繼承的對象 len = arguments.length,//獲取參數的長度
 target = arguments[0],//第一個爲目標對象 arg;//緩存參數對象 //遍歷被繼承的對象 for (; i < len; i++) { //緩存當前對象 arg = arguments[i]; //遍歷被繼承對象中的屬性 for (var property in arg) { //將被繼承對象中的屬性複製到目標對象中 target[property] = arg[property]; } } //返回目標對象 return target;};
/*
 * 這個要出入目標對象(第一個參數--須要繼承的對象) * 也能夠將它綁定到原生對象Object上,這樣全部的對象就能夠擁有這個方法 * */Object.prototype.mix = function () { var i = 0, len = arguments.length,
 arg; for (; i < len; i++) { //緩存當前對象 arg = arguments[i]; //遍歷被繼承對象中的屬性 for (var property in arg) { //將被繼承對象中的屬性複製到目標對象中 this[property] = arg[property]; } }};

多種調用方式 -- 多態
根據參數數量的不一樣 運行不一樣的程序

//多態
function add() {
 //獲取參數 var arg = arguments, len = arg.length;
 switch (len) { //若是沒有參數 case 0: return 10; case 1: return 10 + arg[0]; case 2: return arg[0]+arg[1]; }}

原文

相關文章
相關標籤/搜索