ES 6------class基本用法

9831 ワード

まずclassは実はただの文法糖で、ほとんどの機能はES 5で実現することができます.
クラスのすべてのメソッドはクラスのprototypeに定義されます
class MyFn {}
let a = new MyFn();
a.constructor === MyFn.prototype.constructor // ture

Objectを使ってもいいです.assignクラスに複数のメソッドを追加
Object.assign(MyFn.ptototype, {
    toString() {},
    toValue() {}
})

またMyFn.prototype.constructor === MyFn//true
es 5と一致しない点では,クラス内部定義の手法は枚挙にいとまがない.
Object.keys(MyFn.prototype)  //  []
Object.getOwnPropertyNames(MyFn.prototype)  // ['toString', 'toValue']

constructorメソッド


constructorメソッドはクラスのデフォルトメソッドで、newコマンドでオブジェクトインスタンスを生成するときに自動的に呼び出されるメソッドです.定義が表示されていない場合は、空のconstructorメソッドが自動的に追加され、constructorメソッドはデフォルトでインスタンスオブジェクト(this)を返しますが、別のオブジェクトを返すように指定できます.
class Foo {
    constructor () {
        return Object.create(null);
    }
}

new Foo() instanceof Foo // false

es 5と同様に、インスタンスのプロパティは、定義がそれ自体(すなわちthisオブジェクト)に表示されない限り、プロトタイプに定義されます(prototype)
このコードを見て
var a = new Foo();
var b = new Foo();

a.__proto__.newProperty = function () { console.log("Attention !!!") }
b.newProperty(); // "Attention !!!"

ここで_proto__構造プロトタイプ(すなわちFoo)を指すので、プロトタイプを修正するには慎重にしなければならないので、使わないほうがいい.

Class式を使用すると、即時関数形式を書くことができます。

var foo = class {
    constructor (val) {
        this.value = val;
    }
    printVal () {
        cosole.log(this.value)
    }
}("money")

class変数の昇格は存在しません

new Foo();  // ReferenceError
class Foo {}

注意クラスとモジュールの内部デフォルトは厳格なモードです

classの継承


サブクラスはconstructorでsuperメソッドを呼び出さなければなりません.そうしないと、新しいインスタンスが間違って報告されます.これは、サブクラスが独自のthisオブジェクトではなく、親のthisオブジェクトを継承し、加工するためです.
Es 5の継承は実質的にサブクラスのインスタンスオブジェクトthisを作成してから親クラスのメソッドをthisに追加する(Parent.apply(this);
Es 6の継承は実質的に親クラスのインスタンスオブジェクトthisを作成し、その後、子クラスの構造関数によってthisを修飾する.この場合、サブクラスのthisは親インスタンスの加工に基づいているので、サブクラスでキーワードthisを使用するにはsuperを呼び出す必要があります.

クラスのprototypeと_proto__ ツールバーの


1.サブクラスの_proto__構造関数の継承を表す親クラスを指します.
2.サブクラスのprototype._proto__親クラスのprototypeを指し、メソッドの継承を表す.
class A {};
class B {};
Object.setPrototypeOf(B.prototype, A.prototype);
Object.setPrototypeOf(B, A);
Object.setPrototypeOf = function (obj, proto) {
    obj.__proto__ = proto;
    return obj;
}

受け継がれたいくつかの状況


class A extend Object {}
A.__proto__ === Object   // true
A.prototype.__proto__ === Object.prototype   // true

class A{}は継承が存在しない
A.__proto__ === Function.prototype   // true
A.prototype.__proto__ === Object.prototype   // true

このときAはベースクラスとして関数としてFunctionを直接継承する.prototypeですが、Aが呼び出されたときに返されるのはオブジェクトなので、A.prototype._proto__ Objectを指すprototype 
class A extend null {}
A.__proto__ === Function.prototype   // true
A.prototype.__proto__ === undefined  // true

Object.getPrototypeOf()は、あるクラスが別のクラスを継承しているかどうかを判断するサブクラスから親クラスを取得します.
サブクラスインスタンスの_proto__の_proto__親インスタンスへの__proto__,したがって、親インスタンスの動作は、子クラスで変更できます.
class Foo {}
class Bar extends Foo {}

var a1 = new Foo();
var a2 = new Bar();

a2.__proto__ === a1.__proto__; // false
a2.__proto__.__proto__ === a1.__proto__; // true

a2.__proto__.__proto__.printName = function () {    
    console.log("this is a2")
}
a1.printName() // "this is a2"

アコースティックコンストラクション関数の継承


jsの原生構造関数は約9種類あります
Boolean();  Number();  Array();  String();  Object();  Date();  RegExp(); Error(); Function();
以前はこれらの基本的なコンストラクション関数は継承できませんでしたが、例を挙げると、Arrayコンストラクション関数には定義的な属性を制御する内部属性[[DefineOwnProperty]]があり、この内部属性はサブクラスで取得できないため、サブクラスlength属性の動作が正常ではありません.
でもes 6は
class MyArray extends Array {    
    constructor (...arg) {        
        super(...arg);    
    }
}
var myArray = new MyArray();

classのgetterとsetter


Es 6のgetterとsetterは、属性のdescriptorオブジェクトに定義されています.
Objectを使ってもいいです.getOwnPropertyDescriptor()
class A {    
    constructor () {       ***    }    
    get oneProp () {        ***    }    
    set oneProp () {        ***    }
}
var oDescriptor = Object.getOwnPropertyDescriptor(A , "oneProp");
"get" in oDescriptor; //true
"set" in oDescriptor;  // true

classの静的方法


1つのメソッドの前にstaticキーワードを付けると、このメソッドはインスタンスによって継承されませんが、サブクラスは親の静的メソッドを継承し、静的メソッドはsuperから呼び出すこともできます.

classの静的プロパティ


静的属性とは、インスタンスオブジェクト(this)に定義された属性ではなく、class自体の属性を指し、es 6はclassが静的メソッドのみ静的属性を持たないことを明確に規定する
class Foo {
     
    prop: 1
     
    static prop : 1
}
Foo.prop // undefined 

どちらの方法も無効です.間違いはありませんが.

new.targetプロパティ


newコマンドで呼び出されたコンストラクション関数を返します.コンストラクション関数がnewコマンドで呼び出されていない場合、undefinedが返されます.
次の2つの方法は、コンストラクション関数がnewでのみ呼び出されることを保証するために使用されます.
1.
function Person(name) {    
    if(new.target !== undefined) {       
        this.name = name;    
    }else {        
        throw new Error (" new ")    
    }
}

2.
function Person (name) {    
    if(new.target === Person) {        
        this.name = name;    
    }else {        
        throw new Error (" new ")            
    }
}

class内部呼び出しnew.targetは現在のclassを返し、サブクラスが親クラスを継承するときnew.targetはサブクラスを返すので,この特徴を利用して独立して使用できない,継承して使用するしかないクラスを書くことができる.
class Shape {
    constructor () {
        if(new.target === Shape) {
            throw new Error (" new ")
        }
    }
}
class Rectangle extends Shape {
    constructor () {
        super() 
        ***
    }
}

var x = new Shape() //    
var x = Rectangle()  //   

注意関数の外部でnewを呼び出す.targetはエラーを報告します

Mixinモードの実装


Mixinモードとは、複数のクラスのインタフェースを別のクラスに混入することを意味する
function mix(...mixins) {    
    class Mix {}    
    for (let mixin of minins) {        
        copyProperties(Mix, mixin);        
        copyProperties(Mix.prototype, mixin.prototype);    
    }    
    return Mix;
}
function copyProperties(target, source) {    
    for( let key of Reflect.ownKeys(source)) {        
        if( key !== "constuctor" && 
            key !== "prototype" && 
            key !== "name") {            
        let desc = Object.getOwnPropertyDescriptor(source, key);            
        Object.defineProperties(target, key, desc);        
        }    
    }
}
class DistributedEdit extends mix(Loggable, Serializable) {
    // ..
}