【一】 面向對象的基本概念javascript
面向對象的英文全稱叫作Object Oriented,簡稱OO。OO其實包括OOA(Object Oriented Analysis,面向對象分析)、OOD(Object Oriented Design,面向對象設計)和OOP(Object Oriented Programming,面向對象的程序設計)。java
一般所說的面向對象是指OOP, OOP是一種圍繞真實世界的概念來組織模型的程序設計方法,它採用對象來描述問題空間的實體。在使用計算機解決問題時,對象是做爲計算機模擬真實世界的一個抽象,一個對象就是一個物理實體或邏輯實體,它反映了系統爲之保存信息和(或)與它交互的能力。使其具備本身的屬性和行爲, 從而簡化對復瑣事物的描述,更有利於工程的可維護性和擴展性。編程
OOP同結構化程序設計相比最大的區別就在於: 前者首先關心的是所要處理的數據,然後者首先關心的是功能。app
【二】 面向對象三個基本特徵函數
封裝 (Encapsulation) 將數據以及相關的操做組織在一塊兒,成爲獨立的構件。外部沒法直接訪問這些封裝了的數據,從而保證了這些數據的正確性。封裝的目的是爲了內部數據表現形式和實現細節的隱藏,信息隱藏是爲了減小系統各部分間的依賴性,各部分間必須經過明確的通道傳送信息,也就是對象間的接口.這樣一來,隱藏了部份內部的細節,極大方便系統的開發,維護和擴展。工具
繼承 (Inheritance) 繼承是一種聯結類的層次模型,而且容許和鼓勵類的重用,它提供了一種明確表述共性的方法。一個新類能夠從現有的類中派生,這個過程稱爲類的繼承。新類繼承了原始類的特性,新類稱爲原始類的派生類(子類),而原始類稱爲新類的基類(父類)。派生類能夠從它的基類那裏繼承方法和實例變量,而且派生類能夠修改或增長新的方法使之更適合特殊的需求。繼承性很好地解決了軟件的可重用性問題。this
多態 (Polymorphism) 多態是容許你將父對象設置成爲和一個或更多的他的子對象相等的技術,賦值以後,父對象就能夠根據當前賦值給它的子對象的特性以不一樣的方式運做。簡單的說,就是容許類與類之間相同方法名的指針得以調用, 這樣很好地解決了應用程序函數同名問題。實現多態,有二種方式,覆蓋,重載。編碼
【三】 Javascript 面向對象spa
javascript自己是一種基於對象(object-based)的語言,咱們平常編碼過程當中用到的全部東西幾乎都是對象(Number, String, Boolean, etc.)。可是,相對於一些流行的面嚮對象語言(C++, C#, java),它又不是一種真正的面向對象編程(OOP)語言,由於它的語法中沒有class的概念。prototype
Keyword: class, object, `this`, closure, constructor, prototype
幾種對象封裝的方法
之1、幾種對象封裝的方法
1. 對象封裝 – 原始模式
假定咱們把貓當作一個對象,它有」name」和」color」兩個屬性, 「etc」 行爲。
var Cat = { name: '' color: '', eat: function() {} };
如今,咱們須要根據這個原型對象的規格(schema),生成兩個實例對象。
function eat() { console.log('I\'m eta fish'); } var cat1 = {name: 'Kitty', color: 'white', eat: eat}; var cat2 = {name: 'Smokey', color: 'black', eat: eat}; // var cat3, cat4 ,...
不方便建立多個實例對象,擴展性差, 實例(cat1, cat2)之間找不到聯繫。…
2. 對象封裝 – 構造函數模式
「構造函數」,就是一個普通函數,可是內部使用了 `this` 變量。對函數使用 `new` 運算符,就能生成實例,而且 `this` 變量會綁定在實例對象上。
使用構造器建立出來的對象會有一個 `constructor` 屬性,指向它們的構造函數。
`Class` 只是一個模板,建立出來的來實例都是由模板生成。
好比,貓的原型對象如今能夠這樣寫:
function Cat(name,color){ this.name = name; this.color = color; this.eat = function() { console.log('eat fish'); }; } var cat1 = new Cat('Kitty', 'black'); console.log(cat1.name); // Kitty console.log(cat1 instanceof Cat); // TRUE // 這時 cat1 實例會自動含有一個 `constructor` 屬性,指向它們的構造函數 `Cat`。 var cat2 = Cat('Smokey', 'white'); console.log(cat2); // undefined
3. 對象封裝 – Prototype 模式
`prototype` 是 `Function` 對象的一個屬性,這個屬性指向另外一個對象。 這個對象的全部屬性和方法,都會被構造函數的實例繼承。
同時 `prototype` 又存在一個指向構造函數的引用 `constructor`,這樣就成功的構成一個循環引用的原型鏈結構。
咱們能夠把那些不變的屬性和方法,直接定義在 `prototype` 對象上, 節省內存開銷。
function Cat(name, color) { this.name = name; this.color = color; } Cat.prototype.type = 'mammal'; Cat.prototype.eat = function() { console.log('eat fish'); }; var cat1 = new Cat('Kitty', 'white'); var cat2 = new Cat('Smokey', 'black'); console.log(cat1.type); // mammal console.log(cat1.eta === cat2.eta); // TRUE, same reference console.log(cat1.constructor === Cat) // TRUE, from Person.prototype
之2、繼承 (Inheritance)
將持有共性特色的屬性或行爲抽象出一個基本類, 能夠按不一樣層次結構的業務分組抽象出多個基礎類。
Cat, Bird
1. 繼承 – 構造函數綁定
使用call或apply方法,將父對象的構造函數綁定在子對象上。
function Animal() { this.species = 'animal'; this.sleep = function() { console.log('I\'m sleep at night'); }; } function Cat(name, color) { this.name = name; this.color = color; }
讓`Cat` 繼承 `Animal` 的特性:
/** @class Cat */function Cat(name, color) { Animal.apply(this); this.name = name; this.color = color; } var cat1 = new Cat('Kitty', 'white'); cat1.sleep(); // I am sleep at night
2. 繼承 – 原型鏈繼承
若是」貓」的prototype對象,指向一個Animal的實例,那麼全部」貓」的實例,就能繼承Animal了。
/** @class Cat */function Cat(name, color) { this.name = name; this.color = color; } Cat.prototype = new Animal; Cat.prototype.eta = function() { console.log('fish is my delicious'); };
它至關於徹底刪除了prototype 對象原先的值,而後賦予一個新值
// 任何一個prototype對象都有一個constructor屬性,指向它的構造函數 Cat.prototype.constructor = Cat; // fix prototype chains var cat = new Cat('Kitty', 'fish'); cat.eat(); // fish is my delicious cat.sleep(); // I'm sleep at night' console.log(cat instanceof Cat); // TRUE console.log(cat instanceof Animal); // TRUE
須要建立父類實列來實現 `prototype` 繼承
3. 繼承 (Inheritance) – 利用空對象做爲中介實現原型繼承
var F = function() {}; F.prototype = Animal.prototype; Cat.prototype = new F(); Cat.prototype.constructor = Cat;
咱們將上面的方法,封裝成一個函數,便於使用。
function extend(ctor, superctor, px) { if (!superctor || !ctor) throw Error('extend failed, verify dependencies'); var F = function() {}; F.prototype = superctor.prototype; ctor.prototype = new F(); ctor.prototype.constructor = ctor; ctor.superclass = superctor.prototype; // cache super class proto reference. if (px) { // extend class implements for (var k in px) { if (px.hasOwnProperty(k)) ctor.prototype[k] = px[k]; } } return ctor; }
4 繼承 – 借住工具方法實現繼承
/** @class Mammal */ extend(Cat, Animal, { eat: function() { Cat.superclass.eat.call(this); // call super method console.log('Also i like some ofther food, such as beef and more.'); } }); var cat = new Cat('Smokey', 'fish'); cat.sleep(); cat.eat(); console.log(cat instanceof Animal); console.log(cat instanceof Cat);
之3、多態
1. 多態 – 經過重寫原型方法來實現方法重名調用
/** @class Cat */ extend(Cat, Animal, { eat: function() { Cat.superclass.eat.call(this); // call super method console.log('Also i like some ofther food, such as beef and more.'); } });
2. 多態 (Polymorphism) – 原型繼承 `prototype` 鏈上的方法、屬性查找
【四】總結 Summary
Constructor
Prototype