<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ES6 之 Class 的基本語法和繼承

          共 6455字,需瀏覽 13分鐘

           ·

          2020-12-31 19:48

          來源 |?https://segmentfault.com/a/1190000020652616

          Class 類基本用法

          Class 類完全可以看作構(gòu)造函數(shù)的另一種寫法,類的數(shù)據(jù)類型其實就是函數(shù),類本身也就是其實例的構(gòu)造函數(shù)。使用的時候也是使用 new 命令。
          class Person { constructor(name,age) { this.name = name; this.age = age; }
          getName(){ console.log(`My name is ${this.name}!`) }
          static sayHi() { console.log('Hi'); }}
          let p = new Person();
          typeof Person // "function"p instanceof Person // true

          constructor 方法

          constructor 方法就是類的構(gòu)造方法,this 關(guān)鍵字代表實例對象。其對應(yīng)的也就是 ES5 的構(gòu)造函數(shù) Person。
          constructor 方法是類的默認方法,通過 new 命令生成對象實例時,會自動調(diào)用該方法。一個類必須有 constructor 方法,如果沒有顯式定義,會默認添加一個空的 constructor 方法。
          class Person {}
          Person.prototype // {construtor:f}
          constructor 方法默認返回實例對象,也完全可以 return 另外一個對象。
          class Foo { constructor(){ return Object.create(null); } }
          new Foo() instanceof Foo // false
          類必須使用 new 調(diào)用,也就是 constructor 方法只能通過 new 命令執(zhí)行,否則會報錯。
          class Foo { constructor(){} }
          Foo() // TypeError: Class constructor Foo cannot be invoked without 'new'

          Class 的自定義方法

          Class 類依舊存在 prototype 屬性,且類的所有方法都定義在 prototype 屬性上面。
          class Person { constructor() {} aaa(){} bbb(){}}
          Object.getOwnPropertyNames(Person.prototype) // ["constructor", "aaa", "bbb"]
          prototype 對象的 constructor 屬性,也是直接指向類本身。
          Person.prototype.constructor === Person // truep.constructor === Person // true
          類的新方法可通過?Object.assign?向?prototype?一次性添加多個。
          class Person { constructor() {}}
          Object.assign(Person.prototype, { aaa(){}, bbb(){}})
          注意,定義類的時候,前面不需要加上?function?關(guān)鍵字,也不需要逗號分隔。
          與 ES5 構(gòu)造函數(shù)的不同的是,Class?內(nèi)部所有定義的方法,都是不可枚舉的。
          class Person { constructor() {} aaa(){}}
          Object.keys(Person.prototype) // []Object.getOwnPropertyNames(Person.prototype) // ["constructor", "aaa"]
          而 ES5 的構(gòu)造函數(shù)的?prototype?原型定義的方法是可枚舉的。
          let Person = function(){};Person.prototype.aaa = function(){};
          Object.keys(Person.prototype) // ["aaa"]Object.getOwnPropertyNames(Person.prototype) // ["constructor", "aaa"]
          Class 類的屬性名,可以采用表達式。
          let methodName = 'getName';
          class Person { constructor() {} [methodName](){}}
          Object.getOwnPropertyNames(Person.prototype) // ["constructor", "getName"]

          取值函數(shù) getter 和存值函數(shù) setter

          與 ES5 一樣,在 Class 內(nèi)部可以使用 get 和 set 關(guān)鍵字,對某個屬性設(shè)置存值函數(shù)和取值函數(shù),攔截該屬性的存取行為。
          class Person { constructor() { this.name = 'dora'; } get author() { return this.name; } set author(value) { this.name = this.name + value; console.log(this.name); }}
          let p = new Person();p.author // dorap.author = 666; // dora666
          且其中 author 屬性定義在 Person.prototype 上,但 get 和 set 函數(shù)是設(shè)置在 author 屬性描述對象 Descriptor 上的。
          Object.getOwnPropertyNames(Person.prototype) // ["constructor", "author"]
          Object.getOwnPropertyDescriptor(Person.prototype,'author')// { get: ? author()(),// set: ? author()(value),// ...// }

          Class 的 static 靜態(tài)方法

          類相當(dāng)于實例的原型,所有在類中定義的方法,都會被實例繼承。但如果在一個方法前,加上 static 關(guān)鍵字,就表示該方法不會被實例繼承,而是直接通過類來調(diào)用,這就稱為“靜態(tài)方法”。
          class Person { static sayHi() { console.log('Hi'); }}
          Person.sayHi() // "Hi"
          let p = new Person();p.sayHi() // TypeError: p.sayHi is not a function
          如果靜態(tài)方法包含?this?關(guān)鍵字,這個?this?指的是類,而不是實例。靜態(tài)方法可以與非靜態(tài)方法重名。
          class Person { static sayHi() { this.hi(); }
          static hi(){ console.log('hello') }
          hi(){ console.log('world') }}
          Person.sayHi() // "hello"

          實例屬性的另一種寫法

          實例屬性除了定義在 constructor()?方法里面的 this 上面,也可以定義在類的最頂層。此時定義的時候,屬性前面不需要加上 this。而在類內(nèi)部其它地方調(diào)用的時候,需要加上 this。
          class Person { name = 'dora'; getName() { return this.name; }}
          let p = new Person();p.name // "dora"Object.keys(p) // ["name"]
          這種寫法的好處是,所有實例對象自身的屬性都定義在類的頭部,看上去比較整齊,寫法簡潔,一眼就能看出這個類有哪些實例屬性。

          Class 的繼承

          Class 子類可以通過 extends 關(guān)鍵字實現(xiàn)繼承。
          class Person { constructor() {} sayHi() { return 'Hi'; }}
          class Teacher extends Person { constructor() { super(); }}
          let t = new Teacher();t.sayHi(); // "Hi"

          子類的 constructor

          子類必須在 constructor 方法中調(diào)用 super()?方法,否則新建實例時會報錯。
          如果子類沒有定義 constructor 方法,這個方法會被默認添加,且子類默認添加的 constructor 方法都會默認執(zhí)行 super()?方法。
          class Teacher extends Person {}
          let t = new Teacher();t.sayHi(); // "Hi"
          等同于
          class Teacher extends Person { constructor(...args) { super(...args); }}

          super 關(guān)鍵字

          super 這個關(guān)鍵字,既可以當(dāng)作函數(shù)使用,也可以當(dāng)作對象使用。用法完全不同。

          super() 方法

          super 作為函數(shù)調(diào)用時,代表父類的構(gòu)造函數(shù)。子類的構(gòu)造函數(shù)必須執(zhí)行一次 super()?方法。
          因為 ES6 的繼承機制與 ES5 構(gòu)造函數(shù)不同,ES6 的子類實例對象 this 必須先通過父類的構(gòu)造函數(shù)創(chuàng)建,得到與父類同樣的實例屬性和方法后再添加子類自己的實例屬性和方法。因此如果不調(diào)用 super()?方法,子類就得不到 this 對象。
          super 雖然代表了父類的構(gòu)造函數(shù),但返回的是子類的實例,即通過super 執(zhí)行父類構(gòu)造函數(shù)時,this 指的都是子類的實例。也就是 super()?相當(dāng)于 Person.call(this)。
          class A { constructor() { console.log(this.constructor.name) }}
          class B extends A { constructor() { super(); }}
          new A() // Anew B() // B
          作為函數(shù)時,super()?只能在子類的構(gòu)造函數(shù)之中,用在其他地方就會報錯。

          super 對象

          在普通方法中指向父類的?prototype?原型
          super 作為對象時,在普通方法中,指向父類的 prototype 原型,因此不在原型 prototype 上的屬性和方法不可以通過 super 調(diào)用。
          class A { constructor() { this.a = 3; } p() {return 2;}}A.prototype.m = 6;
          class B extends A { constructor() { super(); console.log(super.a); // undefined console.log(super.p()); // 2 console.log(super.m); // 6 }}
          new B();
          在子類普通方法中通過?super?調(diào)用父類方法時,方法內(nèi)部的?this?指向當(dāng)前的子類實例。
          class A { constructor() { this.x = 'a'; } aX() { console.log(this.x); }}
          class B extends A { constructor() { super(); this.x = 'b'; } bX() { super.aX(); }}
          (new B()).bX() // 'b'
          在靜態(tài)方法中,指向父類
          class A { static m(msg) { console.log('static', msg); } m(msg) { console.log('instance', msg); }}
          class B extends A { static m(msg) { super.m(msg); } m(msg) { super.m(msg); }}
          B.m(1); // "static" 1(new B()).m(2) // "instance" 2
          在子類靜態(tài)方法中通過 super 調(diào)用父類方法時,方法內(nèi)部的 this 指向當(dāng)前的子類,而不是子類的實例。

          任意對象的 super

          由于對象總是繼承其它對象的,所以可以在任意一個對象中,使用 super 關(guān)鍵字,指向的是該對象的構(gòu)造函數(shù)的 prototype 原型。
          let obj = { m() { return super.constructor.name; }};obj.m(); // Object
          注意,使用 super 的時候,必須顯式的指定是作為函數(shù)還是作為對象使用,否則會報錯。
          class B extends A { m() { console.log(super); }}// SyntaxError: 'super' keyword unexpected here

          靜態(tài)方法的繼承

          父類的靜態(tài)方法,可以被子類繼承。
          class Person { static sayHi() { return 'hello'; }}
          class Teacher extends Person {}
          Teacher.sayHi() // "hello"
          在子類的 static 內(nèi)部,可以從 super 對象上調(diào)用父類的靜態(tài)方法。
          class Teacher extends Person { static sayHi() { super.sayHi(); }}
          Teacher.sayHi() // "hello"

          new.target 屬性

          Class 內(nèi)部調(diào)用 new.target,返回當(dāng)前 Class。且子類繼承父類時,new.target 會返回子類。因此利用這個特點,可以寫出不能獨立使用必須繼承后才能使用的類。
          class Shape { constructor() { if(new.target === Shape) { throw new Error('本類不能實例化'); } }}
          class Circle extends Shape { constructor(radius) { super(); console.log('ok'); }}let s = new Shape(); // 報錯let?cir?=?new?Circle(6);??//?'ok'

          本文完?

          瀏覽 26
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人视频欧美 | 蜜桃视频操B网 | 欧美成人免费在线观看 | 日本激情视频网站免费 | 俺去俺来也WWW色老板 |