国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

對javascript繼承的理解

2019-11-20 08:46:43
字體:
來源:轉載
供稿:網友

由于javascript原生是不支持類的(ES6已經支持class與extends),更不用談繼承、多態了,為了模擬出一些其它面向對象編程語言的這些特性,有好多大牛寫了給出了實現方式,看了John Resig的《Simple JavaScript Inheritance》這篇文章,深深被折服了,原來短短幾十行javascript也可以這么強大、優雅,下面以我的理解方式來解讀下。

主要實現了繼承、訪問父類的重名方法(這里的實現方式太妙了),但遺憾的是不能實現成員變量/函數的隱藏。

(function(){  //設置標志位,是new A()過程中還是 B=A.extends({/*   */})過程中;  var initializing = false,      //fnTest 可取結果為倆正則對象 //b_super/b/與 /.*/      //當正則的test方法參數支持自動調用toString()方法時取前面那個      fnTest = /xyz/.test(function(){xyz;}) ? //b_super/b/ : /.*/;      // 創建一個全局的 Class對象  this.Class = function(){};      // 創建繼承函數  Class.extend = function(prop) {    //此處把_super指向父類的prototype,屬性繼承時需要用其判斷父、子是否有同名方法    var _super = this.prototype;          //開始B=A.extends({/*   */});    initializing = true;    //實例化父類,并把父類的實例方法及屬性給prototype    var prototype = new this();    initializing = false;    //結束B=A.extends({/*   */});          // 遍歷用戶傳入的用于構建子類的對象    //處理的地方包括:    //1、屬性直接存到prototype上    //2、方法中沒通過this._super()調用父類中的同名方法,則直接把該方法存到prototype上    //3、方法中有通過this._super()調用父類中的同名方法,則把如下過程包裹成一個函數存到prototype上:    //   把this._super指向父類的同名方法,然后再調用子類的該方法并返回執行結果    for (var name in prop) {      // 循環體中看起來略微復雜,是整個代碼的精華所在      //簡化下此過程就是  v = a && b && c ? d : e; 等同于 v = (a && b && c) ? d : e      //該過程中主要運用的就是邏輯運算中的短路運算 a,b,c全為true則v=d,否則v=e      //a中判斷prop[name]是否是函數,b中判斷父類中是否也有同名的name函數,c主要判斷name函數中是否有調用父類的同名方法(即調用了this._super())      //d就是a,b,c同時滿足的時候,也就是說:name是函數,且name函數存在與父類中,且子類的name函數需要調用了父類的同名函數      //若a,b,c中有一項不滿足則直接把prop[name]給prototype[name]      prototype[name] = typeof prop[name] == "function" &&        typeof _super[name] == "function" && fnTest.test(prop[name]) ?        (function(name, fn){          //首先,先決條件決定了prototype[name]是個函數,所以先包裹一個函數返回          return function() {            //作者這里備份,然后調用fn后又還原this._super            //由于return的是一個function,具有延時調用的作用 所以在子類調用fn時this始終指向子類本身            //而這里的_super是父類的_super,與this._super并無關系,所以備份應該是多余的            //var tmp = this._super;            //this._super指向與fn(即prop[name])同名的父類方法,方便fn內部調用            //這里是實現子類中通過this._super()調用父類同名函數的關鍵            this._super = _super[name];            //此時再調用子類,子類里面的this._super已經指向了父類同名的函數,即_super[name]            var ret = fn.apply(this, arguments);               //this._super = tmp;            //返回執行結果            return ret;          };        })(name, prop[name]) :        prop[name];    }          //此“Class”與外頭那個“Class”是兩個東西    //這個Class實為子類的構造函數    function Class() {      //不是A.extends({/*   */})過程中      if ( !initializing && this.init )        this.init.apply(this, arguments);    }          //前面處理好的prototype綁定給子類的prototype    Class.prototype = prototype;          //修正構造函數    Class.prototype.constructor = Class;        //賦予子類可被繼續繼承的功能    Class.extend = arguments.callee;          return Class;  };})();

如果想更深入了解js繼承,請繼續往下查看文章

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 唐海县| 香河县| 金堂县| 吴忠市| 扎兰屯市| 天柱县| 北票市| 岑溪市| 福海县| 鹤岗市| 南平市| 彭泽县| 衢州市| 曲阳县| 凌云县| 斗六市| 湖南省| 宜昌市| 孟村| 缙云县| 梓潼县| 绍兴县| 若尔盖县| 晋城| 治多县| 高阳县| 富蕴县| 昌江| 日土县| 西和县| 鄯善县| 保山市| 钟山县| 镶黄旗| 交城县| 六盘水市| 呼伦贝尔市| 格尔木市| 吉木乃县| 海门市| 张家港市|