茄子在线看片免费人成视频,午夜福利精品a在线观看,国产高清自产拍在线观看,久久综合久久狠狠综合

    <s id="ddbnn"></s>
  • <sub id="ddbnn"><ol id="ddbnn"></ol></sub>

  • <legend id="ddbnn"></legend><s id="ddbnn"></s>

    JS面向?qū)ο缶幊淘斀?/div>
    來源:易賢網(wǎng) 閱讀:909 次 日期:2016-08-02 14:51:10
    溫馨提示:易賢網(wǎng)小編為您整理了“JS面向?qū)ο缶幊淘斀狻?方便廣大網(wǎng)友查閱!

    序言

    在JavaScript的大世界里討論面向?qū)ο?,都要提到兩點(diǎn):1.JavaScript是一門基于原型的面向?qū)ο笳Z言 2.模擬類語言的面向?qū)ο蠓绞?。?duì)于為什么要模擬類語言的面向?qū)ο?,我個(gè)人認(rèn)為:某些情況下,原型模式能夠提供一定的便利,但在復(fù)雜的應(yīng)用中,基于原型的面向?qū)ο笙到y(tǒng)在抽象性與繼承性方面差強(qiáng)人意。由于JavaScript是唯一一個(gè)被各大瀏覽器支持的腳本語言,所以各路高手不得不使用各種方法來提高語言的便利性,優(yōu)化的結(jié)果就是其編寫的代碼越來越像類語言中的面向?qū)ο蠓绞剑瑥亩惭谏w了JavaScript原型系統(tǒng)的本質(zhì)。

    基于原型的面向?qū)ο笳Z言

    原型模式如類模式一樣,都是是一種編程泛型,即編程的方法論。另外最近大紅大紫的函數(shù)編程也是一種編程泛型。JavaScript之父Brendan Eich在設(shè)計(jì)JavaScript時(shí),從一開始就沒打算為其加入類的概念,而是借鑒了另外兩門基于原型的的語言:Self和Smalltalk。

    既然同為面向?qū)ο笳Z言,那就得有創(chuàng)建對(duì)象的方法。在類語言中,對(duì)象基于模板來創(chuàng)建,首先定義一個(gè)類作為對(duì)現(xiàn)實(shí)世界的抽象,然后由類來實(shí)例化對(duì)象;而在原型語言中,對(duì)象以克隆另一個(gè)對(duì)象的方式創(chuàng)建,被克隆的母體稱為原型對(duì)象。

    克隆的關(guān)鍵在于語言本身是否為我們提供了原生的克隆方法。在ECMAScript5中,Object.create可以用來克隆對(duì)象。

    var person = {

      name: "tree",

      age: 25,

      say: function(){

        console.log("I'm tree.")

      }

    };

    var cloneTree = Object.create(person);

    console.log(cloneTree);

    原型模式的目的并不在于得到一個(gè)一模一樣的對(duì)象,而提供了一種便捷的方式去創(chuàng)建對(duì)象(出自《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》)。但是由于語言設(shè)計(jì)的問題,JavaScript的原型存在著諸多矛盾,它的某些復(fù)雜的語法看起來就那些基于類的語言,這些語法問題掩蓋了它的原型機(jī)制(出自《JavaScript語言精粹》)。如:

    function Person(name, age){

      this.name = name;

      this.age = age;      

    }

    var p = new Person('tree', 25)

    實(shí)際上,當(dāng)一個(gè)函數(shù)對(duì)象唄創(chuàng)建時(shí),F(xiàn)unction構(gòu)造器產(chǎn)生的函數(shù)對(duì)象會(huì)運(yùn)行類似這樣的一些代碼:

    this.prototype = {constructor: this}

    新的函數(shù)對(duì)象被賦予一個(gè)prototype屬性,它的值是一個(gè)包含constructor屬性且屬性值為該新函數(shù)的對(duì)象。當(dāng)對(duì)一個(gè)函數(shù)使用new運(yùn)算符時(shí),函數(shù)的prototype的屬性的值被作為原型對(duì)象來克隆出新對(duì)象。如果new運(yùn)算符是一個(gè)方法,它的執(zhí)行過程如下:

    Function.prorotype.new = function() {

      //以prototype屬性值作為原型對(duì)象來克隆出一個(gè)新對(duì)象

      var that = Object.create(this.prorotype);

       

      //改變函數(shù)中this關(guān)鍵指向這個(gè)新克隆的對(duì)象

      var other = this.apply(that, arguments);

       

      //如果返回值不是一個(gè)對(duì)象,則返回這個(gè)新克隆對(duì)象

      return (other && typeof other === 'object') ? other : that;

    }

    從上面可以看出,雖然使用new運(yùn)算符調(diào)用函數(shù)看起來像是使用模板實(shí)例化的方式來創(chuàng)建對(duì)象,但本質(zhì)還是以原型對(duì)象來克隆出新對(duì)象。

    由于新克隆的對(duì)象能否訪問到原型對(duì)象的一切方法和屬性,加上new運(yùn)算符的特性,這便成了利用原型模擬類式語言的基石。 

    利用原型模擬類式語言

    抽象

    用原型模式來模擬類,首先是抽象方式。根據(jù)JavaScript語言的特點(diǎn),通常一個(gè)類(實(shí)際上是偽類)通常是將字段放置于構(gòu)造函數(shù)(實(shí)際上是new 運(yùn)算符調(diào)用的函數(shù),JavaScript本身并沒有構(gòu)造函數(shù)的概念)中,而將方法放置于函數(shù)的prototype屬性里。

    function Person(name, age) {

      this.name = name;

      this.age = age;

    };

    Person.prototype.say = function(){

      console.log("Hello, I'm " + this.name);

    };

    繼承

    繼承是OO語言中的一個(gè)最為人津津樂道的概念。許多OO語言都支持兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承之繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。但是ECMAScript中無法實(shí)現(xiàn)接口繼承,只支持實(shí)現(xiàn)繼承,而且其實(shí)現(xiàn)繼承主要是依靠原型鏈來實(shí)現(xiàn)的。(出自《JavaScript高級(jí)程序設(shè)計(jì)》 6.3節(jié)——繼承)在高三中作者探索了各種關(guān)于繼承的模擬,如:組合繼承、原型繼承、寄生繼承、寄生組合繼承,最終寄生組合式成為所有模擬類式繼承的基礎(chǔ)。

    function Person(name, age) {

      this.name = name;

      this.age = age;

    };

    Person.prototype.say = function(){

      console.log("Hello, I'm " + this.name);

    };

    function Employee(name, age, major) {

      Person.apply(this, arguments);

      this.major = major;

    };

    Employee.prototype = Object.create(Person.prototype);

    Employee.prorotype.constructor = Employee;

    Employee.prorotype.sayMajor = function(){

      console.log(this.major);

    }

    高三中只給出了單繼承的解決方案,關(guān)于多繼承的模擬我們還得自己想辦法。由于多繼承有其本身的困難:面向?qū)ο笳Z言如果支持了多繼承的話,都會(huì)遇到著名的菱形問題(DiamondProblem)。假設(shè)存在一個(gè)如左圖所示的繼承關(guān)系,O中有一個(gè)方法foo,被A類和B類覆寫,但是沒有被C類覆寫。那么C在調(diào)用foo方法的時(shí)候,究竟是調(diào)用A中的foo,還是調(diào)用B中的foo?

    名單

    所以大多數(shù)語言并不支持多繼承,如Java支持單繼承+接口的形式。JavaScript并不支持接口,要在一個(gè)不支持接口的語言上去模擬接口怎么辦?答案是著名的鴨式辨型。放到實(shí)際代碼中就是混入(mixin)。原理很簡單:

    function mixin(t, s) {

       for (var p in s) {

         t[p] = s[p];

       }

     }

    值得一提的是dojo利用MRO(方法解析順序(Method Resolution Order),即查找被調(diào)用的方法所在類時(shí)的搜索順序)方式解決了多繼承的問題。

    到此,我們已經(jīng)清楚了模擬類語言的基本原理。作為一個(gè)愛折騰的程序員,我希望擁有自己的方式來簡化類的創(chuàng)建:

    提供一種便利的方式去創(chuàng)建類,而不暴露函數(shù)的prototype屬性

    在子類中覆蓋父類方法時(shí),能夠像Java一樣提供super函數(shù),來直接訪問父類同名方法

    以更方便的方式添加靜態(tài)變量和方法而不去關(guān)心prototype

    像C#那樣支持Attribute

    最終,在借鑒各位大牛的知識(shí)總結(jié),我編寫了自己的類創(chuàng)建工具O.js:

    (function(global) {

      var define = global.define;

      if (define && define.amd) {

        define([], function(){

          return O;

        });

      } else {

        global.O = O;

      }

      function O(){};

      O.derive = function(sub) {

        debugger;

        var parent = this;

        sub = sub ? sub : {};

        var o = create(parent);

        var ctor = sub.constructor || function(){};//如何調(diào)用父類的構(gòu)造函數(shù)?

        var statics = sub.statics || {};

        var ms = sub.mixins || [];

        var attrs = sub.attributes || {};

        delete sub.constructor;

        delete sub.mixins;

        delete sub.statics;

        delete sub.attributes;

        //處理繼承關(guān)系

        ctor.prototype = o;

        ctor.prototype.constructor = ctor;

        ctor.superClass = parent;

        //利用DefineProperties方法處理Attributes

        //for (var p in attrs) {

          Object.defineProperties(ctor.prototype, attrs);

        //}

        //靜態(tài)屬性

        mixin(ctor, statics);

        //混入其他屬性和方法,注意這里的屬性是所有實(shí)例對(duì)象都能夠訪問并且修改的

        mixin(ctor.prototype, sub);

        //以mixin的方式模擬多繼承

        for (var i = 0, len = ms.length; i < len; i++) {

          mixin(ctor.prototype, ms[i] || {});

        }

        ctor.derive = parent.derive;

        //_super函數(shù)

        ctor.prototype._super = function(f) {

          debugger;

          return parent.prototype[f].apply(this, Array.prototype.slice.call(arguments, 1));

        }

        return ctor;

      }

      function create(clazz) {

        var F = function(){};

        F.prototype = clazz.prototype;

        //F.prototype.constructor = F; //不需要

        return new F();

      };

      function mixin(t, s) {

        for (var p in s) {

          t[p] = s[p];

        }

      }

    })(window);

    類創(chuàng)建方式如下:

    var Person = O.derive({

      constructor: function(name) {//構(gòu)造函數(shù)

        this.setInfo(name);

      },

      statics: {//靜態(tài)變量

        declaredClass: "Person"

      },

      attributes: {//模擬C#中的屬性

        Name: {

          set: function(n) {

            this.name = n;

            console.log(this.name);

          },

          get: function() {

            return this.name + "Attribute";

          }

        }

      },

      share: "asdsaf",//變量位于原型對(duì)象上,對(duì)所有對(duì)象共享

      setInfo: function(name) {//方法

        this.name = name;

      }

    });

    var p = new Person('lzz');

    console.log(p.Name);//lzzAttribute

    console.log(Person);

    繼承:

    var Employee = Person.derive({//子類有父類派生

      constructor: function(name, age) {

        this.setInfo(name, age);

      },

      statics: {

        declaredClass: "Employee"

      },

      setInfo: function(name, age) {

        this._super('setInfo', name);//調(diào)用父類同名方法

        this.age = age;

      }

    });

    var e = new Employee('lll', 25);

    console.log(e.Name);//lllAttribute

    console.log(Employee);

    以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

    更多信息請(qǐng)查看網(wǎng)絡(luò)編程
    易賢網(wǎng)手機(jī)網(wǎng)站地址:JS面向?qū)ο缶幊淘斀?/a>
    由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

    2026上岸·考公考編培訓(xùn)報(bào)班

    • 報(bào)班類型
    • 姓名
    • 手機(jī)號(hào)
    • 驗(yàn)證碼
    關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
    工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)