(一)面向对象的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
相关文章
相关标签/搜索