<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## es6類功能測試 ### es5和es6比較 關鍵詞:`靜態方法`、`static` **注意事項**: 1. 我們仍然可以使用es5 `類.prototype` 的方式綁定公用方法和屬性 2. es6雖然不支持靜態屬性,但可以通過 `類.x` 的方式達到靜態屬性的效果。 3. 我們無法像es5構造函數一樣將`類`當做函數執行 ``` // 1) class Child{ constructor(){ } //靜態方法 static echo(){ console.log('這是一個靜態方法'); } } Child.a = 1; //相當于靜態屬性 console.log(Child.a); //1 Child.echo(); //這是一個靜態方法 Child.prototype.b = 2; let c1 = new Child(); console.log(c1.b); //2 Child(); //TypeError: Class constructor Child cannot be invoked without 'new' ``` ### 關于繼承 - 當不填` constructor` 時,使用了繼承的子類可以順利得到父類給實例的 `私有屬性和方法`。 - 子類可以繼承到父類原型上的方法以及父類的靜態方法 ``` // 1) class Parent{ constructor(){ this.a = 1; //私有屬性 } echo(){ console.log('我是Parent中的方法'); } } class Child extends Parent{ //沒有填寫constructor } let c1 = new Child(); console.log(c1) //{a:1} console.log(c1.constructor) // [Function:Child] c1.echo(); //我是Parent中的方法 ``` - 當填了 `constructor`,必須調用 `super` 方法,否則會報以下錯誤。 ``` // 2) class Parent{ constructor(){} } class Child extends Parent{ constructor(){} } let c1 = new Child(); <<< ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor ``` - 當父類在構造函數中返回一個對象時,子類的實例將會是這個對象。 - 這個對象不會包含父類以及子類原型上的方法(但子類仍然可以繼承到父類的靜態方法) - 這個對象的 `constructor` 指向的是 `Object構造函數`,而不是子類或父類的構造函數 ``` // 3) class Parent{ constructor(){ this.a = 2; return { a:1 }; } echo(){ console.log('我是Parent中的方法'); } static echo(){ console.log('我是Parent中的靜態方法'); } } class Child extends Parent{ constructor(){ super(); this.b = 2; } notice(){ console.log('我是子類中的方法') } } let c1 = new Child(); console.log(c1); //{a:1,b:2} console.log(c1.constructor); //Function Object console.log(c1 instanceof Child); //false console.log(c1 instanceof Parent); //false console.log(c1 instanceof Object); //true Child.echo(); //我是Parent中的靜態方法 c1.notice(); //c1.notice is not a function c1.echo(); //TypeError: c1.echo is not a function ``` ## 關于類的構造函數的指向 構造函數的指向(`__proto__`)是指向 `Function` 構造函數的原型的 ``` console.log(Object.getPrototypeOf(a)===Function.prototype); //true ``` **注意**: > 這里說的是構造函數的指向,而不是構造函數原型的指向 ## 使用es5實現es6的類 首先我們先定義兩個構造函數 ``` function Parent(){}; function Child(){}; ``` 如果是es6,我們要實現繼承的話只需要`Child extends Parent`即可,但es5顯然是不存在這種語法糖的,我們需要通過把構造函數包裝進一個函數中(這個函數其實就是所謂的類),通過函數自執行時傳入的參數來決定這個類繼承自誰。 **這也是通過class創建的類,去掉語法糖的皮,編譯過后,真正的運行時的樣子。** ``` var Child = function(Parent){ _inherits(Child,Parent); function Child(){} return Child; }(Parent) var Parent = function(){ function Parent(){}; return Parent; }() ``` 注意我們在匿名函數自執行時使用了一個方法 `_inherits` 來具體實現類的繼承。 ``` function _inherits(subCon,superCon){ // 繼承父類prototype上的方法(公有方法) let subCon.prototype = Object.create(superCon.prototype,{constructor:{value:subCon}}); // 繼承父類的static方法(靜態方法) subCon.__proto__ = superCon; } ``` 除此之外子類還需要繼承父類的私有屬性和方法 ``` var Child = function(Parent){ ... function Child(){ Object.getPrototypeOf(Child).call(this); //在上面的_inheris方法中我們已經將Child__proto__ = Parent,故這里的getPrototypeOf 即為 Parent } return Child; }(Parent) ``` 并且當父類返回的是一個對象時,我們子類實例化時返回的對象也要變成這個父類返回的對象。 ``` var Child = function(Parent){ ... function Child(){ let ret = this; let o = Object.getPrototype(Child).call(this); if(typeof o === 'object'){ ret = o; // 還可以在這里進行一些子類的私有屬性和方法的掛載 } return ret; } return Child; }(Parent) ``` 除此之外,我們需要確保類只能用 `new ` 來實例化,而不能單獨執行。(我們不能像es5一樣讓構造函數像普通函數一樣執行) So我們在構造函數調用時候使用了一個 `__classCallCheck` 方法來檢查類 這個方法之所以有效的原因在于,如果是像調用普通函數一樣調用類,那么此時的 `this` 應該指向的是 `window ` or `undefined` ,這兩貨顯然不是Child的實例。 ``` function _classCallCheck(instance,constructor){ //檢查當前類 有沒有使用new if(!(instance instanceof constructor)) throw Error('Without new'); } ... function Child(){ _classCallCheck(this,Child); ... } ... ``` 另外當我們在 `class` 中聲明一個公共方法或則靜態方法時,內部其實調用的是 `defineProperty` 來給構造函數的原型和構造函數本身上添加屬性來實現的。 ``` ... function Parent(){ ... _createClass(Parent,[ //公共方法 {key:'publicFn',value:function(){ console.log(1); }} ... ],[ //靜態方法 {key:'staticFn',value:function(){ console.log(2); }} ]) } ... function _createClass(target,protoProperties,staticProperties){ if(protoProperties){ defineProperties(target.prototype,protoProperties); } if(staticProperties){ defineProperties(target,staticProperties); } } function defineProperties(target,properties){ var conf = {configurable:true,writable:true,enumerable:true} for(var i=0;i<properties.length;++i){ conf.value = properties[i].value; Object.defineProperty(target,properties[i].key,conf); } } ``` ### 源碼 > 點擊獲取源碼 [github](https://github.com/fancierpj0/es6-class)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看