(一)面向對象的javascript

javascript是一門典型的動態類語言javascript

一:鴨式辨型(指導咱們關注對象的行爲,而不關注對象自己)。java

    var duck = {
        duckString: function(){
            console.log("嘎嘎")
        }
    };

    var chicken = {
        duckString: function(){
            console.log("嘎嘎")
        }
    }

    var choir = []; //合唱團
    
    var joinChoir = function( animal ){
        if (animal && typeof animal.duckString === 'function') {
            choir.push(animal);
            console.log('恭喜加入合唱團')
            console.log('合唱團已經有的數量:'+ choir.length)
        }
    }

    joinChoir(duck)
    joinChoir(chicken)

對於加入合唱團,無需關心他們的類型,而只是確保它有duckString方法。api

二:多態瀏覽器

多態的實際含義是,同一操做做用於不一樣的對象上面,能夠產生不一樣的解釋,執行不一樣的結果。 (其實是把「作什麼」和「誰去作」分離開來)函數

    var makeSound = function( animal ) {
        if ( animal instanceof Dcuk) {
            console.log("嘎嘎")
        } else if ( animal instanceof Chiken) {
            console.log("咯咯")
        }
    }

    var Dcuk = function(){};
    var Chiken = function(){};

    makeSound(new Dcuk)
    makeSound(new Chiken)

(1多態的度複雜性this

    var makeSound = function( animal ) {
        animal.sound()
    }

    var Dcuk = function() {};
    var Chiken = function() {};
    var Dog = function() {};

    Dcuk.prototype.sound = function() {
        console.log("嘎嘎嘎")
    }

    Dog.prototype.sound = function() {
        console.log("汪汪汪")
    }

    makeSound(new Dcuk)
    makeSound(new Dog)

將行爲分享在各個對象中,並讓這些對象各自負責本身的行爲,這正是面向對象優勢google

假設咱們要編寫一個地圖應用,如今有兩家可選的地圖api提供商供咱們接入本身的應用。目前咱們選擇谷歌地圖,谷歌地圖中提供show()方法,負責在頁面上展現整個地圖。spa

    var googleMap = {
        show: function() {
            console.log('開始渲染地圖')
        }
    }

    var renderMap = function() {
        googleMap.show()
    }

    renderMap()

後來由於某些緣由,咱們要將谷歌地圖轉化爲百度地圖,爲了讓renderMap函數保持必定的彈性,咱們使用一些條件分支來讓renerMap函數同時支持谷歌地圖和百度地圖prototype

    var googleMap = {
        show: function() {
            console.log("渲染谷歌地圖")
        }
    }

    var baiduMap = {
        show: function() {
            console.log("渲染百度地圖")
        }
    }

    var renderMap = function( type ){
        if ( type === 'google') {
            googleMap.show()
        } else if ( type === 'baidu') {
            baiduMap.show()
        }
    }

    renderMap('baidu')
    renderMap('google')

雖然renderMpa函數保持了必定的彈性 ,可是這種彈性是很脆弱的,一旦替換成搜狗地圖,那無疑須要改動renderMap()函數,繼續往裏邊堆砌條件分支語句。code

    var renderMap = function ( map ){
        if (map.show instanceof Function) {
            map.show();
        }
    }

    var sosoMap = {
        show: function() {
            console.log("搜搜地圖開始渲染")
        }
    }
    renderMap(googleMap)
    renderMap(baiduMap)
    renderMap(sosoMap)

如今咱們來找找這段代碼的多態性,當咱們向谷歌地圖對象和百度地圖對象發出「展現地圖的」請求時。會分別調用他們的show()方法。會產生不一樣的執行結果。對象的多態性提示咱們,「作什麼」和「怎麼去作」是能夠分開的,即便之後增長了搜搜地圖,renderMap函數任然不須要作出什麼改變。

三 封裝

封裝的目的是將信息隱藏,通常而言,咱們討論的封裝是封裝數據和封裝實現。
這裏咱們將說明下更廣義的封裝,不只包括封裝數據和封裝實現,還包括封裝類型和封裝變化

1。封裝數據
在許多語言的對象系統中,封裝數據是由語法解析實現的,這些語言提供了private, public, protected等關鍵字來提供不一樣的訪問權限

javascript沒有提供對這些關鍵字的支持,咱們只能依賴變量的做用域來實現封裝特性,並且只能模擬出public,private這兩種封裝。

除了ES6的let以外,咱們通常經過函數來建立做用域。

    var myObject = (function() {
        var _name = 'seven'; //私有private變量
        return {
            getName : function() { //公開public變量
                return _name; 
            }
        }
    })();

    console.log(myObject._name) ;//undefined
    console.log(myObject.getName()) ;//seven

另外,在ES6中,還能夠經過Symbol建立私有屬性

四:使用克隆的原型模式

若是使用原型模式,咱們只須要負責克隆的方法,變能完成一樣的功能。
原型模式使用的關鍵,是語言自己是否提供了克隆的方法,ES5提供了Object.create方法,代碼以下

    var Plane = function() {
        this.blood = 100;
        this.attackLevel = 1;
        this.defenseLevel = 1;
    };

    var _plane = new Plane()
    _plane.blood = 500;
    _plane.attackLevel = 2;
    _plane.defenseLevel = 2;

    var clonePlane = Object.create( _plane );
    console.log( clonePlane ) // {blood: 500, attackLevel: 2, defenseLevel: 2}

    //不支持Object.create方法的瀏覽器中,能夠使用如下代碼
    Object.create = Object.create || function( obj ) {
        var F = function() {};
        F.prototype = obj;

        return new F();
    }

原型繼承

在javascript語言裏,咱們並不關心克隆的細節,由於這是引擎內部實現的。咱們只是顯式的調用
var object1 = new Object()或者 var object2 = {};此時,引擎內部會從Object.protype上面克隆出一個對象來,咱們最終獲得的就是這個對象。

咱們看看經過new運算符從構造器中獲得一個對象,下面的代碼最熟悉不過了。

    function Preson( name ) {
        this.name = name;
    }
    var a = new Preson("seven2");
    console.log(a.name) //seven2

    Preson.prototype.getName = function() {
        return this.name
    }

    console.log(a.getName()) //seven2

對象會記住它的原型。

    var b = new Object();
    console.log(b.__proto__ === Object.prototype) ;//true

附上咱們最經常使用的原型繼承方式

    var obj = {name:'seven3'};
    var A = function(){};
    A.prototype = obj; //{name:'seven3'};
    var aa = new A()
    console.log(aa.name)

咱們常指望一個類繼承另一個類時 ,每每使用如下代碼來模擬

  var AA = function() {};
  AA.prototype = {name:"seven4"}

  var BB = function() {};
  BB.prototype = new AA()

  var bb = new BB();
  console.log(bb.name);//seven4
相關文章
相關標籤/搜索