ES 6の何はクラスですか?

12032 ワード

伝統的なjavascriptの中には対象だけあって、類の概念がありません.原型に基づいたオブジェクト指向言語です.プロトタイプオブジェクトの特徴は、自分の属性を新しいオブジェクトに共有することです.このような書き方は他の伝統的な対象言語に対して、独特な印象を持っています.非常に困惑しやすいです.
まずみんなは分かります.なぜクラスが現れますか?
まず私たちのJavaScriptプログラミング思想の発展史を振り返ってみます.JSが生まれた時から、初めはプロセス指向のプログラミングをしていました.一つの問題を説明してくれました.何行かのjsでできます.jsの発展とブラウザーがjsに対して実行速度がますます高くなります.私達はjsの実現の機能についてますます多くなって、コードの量に伴ってますます多くなることができて、私達は依然としてプロセスに向かうプログラミングの方案を使って、問題があります.私たちは怪獣ゲームを作ります.
攻撃function ateck()
エスケープfunction escape()
加血function reume()
この3つの方法の具体的な実現に注目して、これらの方法を繰り返し呼び出してゲームを完成します.これは過程に向かう考え方です.モンスターを打つ使用者を増やすと、単純にこのいくつかの方法で複数のゲームを完成させるには足りません.私たちはより高級な思想を対象にしたいです.javascriptは対象に向けた特徴がないにもかかわらず、(継承、パッケージ、多形).しかし、私たちはこのような考え方でこのような需要を書き換えることができます.
function BraveMan() {
}
BraveMan.prototype.attack = function () {}
Braveman.prototype.escape = function () {}
BraveMan.prototype.resume = function() {}
このような構造関数をカプセル化して,このようなプロセスを複数回実行できるオブジェクトを生成するために,私たちのもとのプロセスに基づいている.こうすれば、私たちのモンスターを殴るのは、単にモンスターを打つだけではなく、モンスターを打つことができる人(対象に向かって考えるような)になります.ここの勇者は私たちが望む対象です.これもこのような思想が私達にもたらす利益であり、モジュール化、拡張などの利点です.
私たちの日常的なcodengの中で、多くの大きなプロジェクトの中で、このようなオブジェクト指向の思想を使ってプログラムを行う必要があります.Javascriptの中には対象に向かっていないです.私たちが採用している似たようなオブジェクト指向のプロセスは、プロトタイプに基づいてプログラミングします.以下は仕事中のコードです.
// ControlIndex   
function ControlIndex(len) {
    // this    Control   
    // Control            index      0
    // len        
    this.index = 0;
    this.len = len;
}

//            
ControlIndex.prototype = {
    prev: function () {
        return this.getIndex(-1);
    },
    next: function () {
        return this.getIndex(1);
    },
    getIndex: function (val) {
        var index = this.index;
        var len = this.len;
        var curIndex = (index + val + len) % len;
        this.index = curIndex;
        return curIndex;
    }
}

// AudioManager   
function AudioManager(){
    //        audio   
    this.audio = new Audio();
    //         
    this.status = 'pause';
}
AudioManager.prototype = {
    play:function(){
        this.audio.play();
        this.status = 'play';
    },
    pause:function(){
        this.audio.pause();
        this.status = 'pause';
    },
    setAudioSource:function(src){
        this.audio.src = src;
        //         
        this.audio.load();
    }
}
ここで使用されるプロトタイププログラミングの一例に基づいて、一つのプロジェクトの異なるモジュールを分解し、各モジュールはこのような方式でプログラミングする.多重性がより良く、同時に分業が明確であり、A方法でB方法を完成するだけでなく、統一的に管理対象に任せてこれらの方法を実行する.
Javascriptの関数にとって、私たちの関数は多くの不完全なところからなります.まず、function声明の関数を通じて、声明できます.普通の方法、構造関数、単純にこの二つの関数は法律によって区別されません.また問題が発生しやすく、構造関数を普通の関数として実行すると、グローバル変数が発生し、エラーが発生する可能性があります.
上の様々な現象に基づいて、私たちは同じような対象に向かう思想でプログラミングする必要があります.私たちのオリジナルのfunction宣言の構造関数は、制約性、安全性が足りず、このような思想を支持するには不十分です.
だから、新しい文法規範の中でECMAScript 6にクラスを導入しました.元のfunctionの方式に基づいて、文法飴を使って、もっと便利で、安全で、目的性がもっと強いです.
ES 6にはクラスという概念が導入されており、クラスをキーワードとして定義することができます.このキーワードの出現によって、オブジェクトの書き方がより明確になり、対象に向けた言語のようになります.ES 6の書き方はこのようになります.
class Person{//         Person   
    constructor(name,age){//constructor        ,      
        this.name = name;//this         
        this.age=age;
    }
    say(){//        ,         function
        return "     " + this.name+"  "+this.age+"  ";
    }
}
var obj=new Person("yinchengnuo",18);
console.log(obj.say());//      yinchengnuo   18   
ただし、注意すべき点は:
1.種類の中で方法を声明する時、この方法にfunctionキーワードを加えないでください.
2.方法間はカンマで区切らないでください.誤報があります.
以下のコードからクラスは実質的に関数であることが分かります.クラス自体が指すのは構造関数です.ES 6のクラスは実は構造関数の別の書き方だと考えられます.
console.log(typeof Person);//function
console.log(Person===Person.prototype.constructor);//true
以下のコードはコンストラクションのprototype属性を説明し、ES 6のクラスには依然として存在しています.
console.log(Person.prototype);//          
実際にはクラスのすべての方法がクラスのプロタイプの属性に定義されています.一緒に証明してみましょう.
Person.prototype.say=function(){//            。       !
 return "      ,  " + this.name+"  "+this.age+"  ";
}
var obj=new Person("yinchengnuo",23);
console.log(obj.say());//      ,   yinchengnuo   23   
もちろんプロトタイプ属性によるクラス追加も可能です.以下のとおりです
Person.prototype.laodeng=function(){
    return "     prototype       ,    yyy";
}
var obj=new Person("ycn",18);
console.log(obj.laodeng());//     prototype       ,   yyy
Object.assign法によりオブジェクトの動的な増加方法も可能である.
Object.assign(Person.prototype,{
    getName:function(){
        return this.name;
    },
    getAge:function(){
        return this.age;
    }
})
var obj=new Person("ycn",1);
console.log(obj.getName());//ycn
console.log(obj.getAge());//1
constructorメソッドは、カテゴリのコンストラクタのデフォルトの方法であり、newコマンドによりオブジェクトインスタンスを生成すると、自動的にこの方法を呼び出します.
class Box{
    constructor(){
        console.log("   ,       ");//              。
    }
}
var obj=new Box();
constructorの方法は明示的な定義がないと、暗黙的にconstructorの方法を生成します.構造関数が追加されていなくても、構造関数は存在します.constructor方法はデフォルトではインスタンスオブジェクトthisを返すが、constructor方法を指定して新たなオブジェクトを返すことができ、このクラスのインスタンスオブジェクトではないようにする.
class Desk{
    constructor(){
        this.xixi="666";
    }
}
class Box{
    constructor(){
        return new Desk();//       this,           
    }
}
var obj=new Box();
console.log(obj.xixi);//666
constructorで定義されている属性は、インスタンス属性(すなわち、thisオブジェクトに定義されている)と呼ばれることができ、constructor外の宣言の属性は、すべて原型上に定義されており、原型属性(つまり、class上に定義されている)と呼ばれることができる.hasOwn Property()関数は、属性がインスタンス属性であるかどうかを判断します.結果はブール値です.trueはインスタンス属性であり、falseはインスタンス属性ではないと説明しています.in演算子は、オブジェクトを介して指定された属性にアクセスできるときにtrueを返します.属性がインスタンスに存在するか、プロトタイプに関係なく.
class Box{
    constructor(num1,num2){
        this.num1 = num1;
        this.num2=num2;
    }
    sum(){
        return num1+num2;
    }
}
var box=new Box(12,88);
console.log(box.hasOwnProperty("num1"));//true
console.log(box.hasOwnProperty("num2"));//true
console.log(box.hasOwnProperty("sum"));//false
console.log("num1" in box);//true
console.log("num2" in box);//true
console.log("sum" in box);//true
console.log("say" in box);//false
クラスのすべてのインスタンスは、プロトタイプのオブジェクトを共有します.プロト属性は同じです.
class Box{
    constructor(num1,num2){
        this.num1 = num1;
        this.num2=num2;
    }
    sum(){
        return num1+num2;
    }
}
//box1   box2    Box    。   __proto__    Box   prototype
var box1=new Box(12,88);
var box2=new Box(40,60);
console.log(box1.__proto__===box2.__proto__);//true
これにより、プロトによるクラス追加方法もあります.例のプロト属性を使ってプロトタイプを書き換えると、クラスのオリジナル定義が変更され、すべてのインスタンスに影響を与えますので、使用を勧めません.
class Box{
    constructor(num1,num2){
        this.num1 = num1;
        this.num2=num2;
    }
    sum(){
        return num1+num2;
    }
}
var box1=new Box(12,88);
var box2=new Box(40,60);
box1.__proto__.sub=function(){
    return this.num2-this.num1;
}
console.log(box1.sub());//76
console.log(box2.sub());//20
classには変数が存在しないので、先に定義してから使用する必要があります.ES 6はクラスの声明をコードヘッダにアップグレードしませんが、ES 5は異なります.ES 5は変数が存在します.先に定義してから定義します.
//ES5         ,      
new A();
function A(){
}
//ES6         ,           
new B();//B is not defined
class B{
}
これはES 6のクラスの概念に対する理解です.クラスを提出した以上、このクラスはどうやって実現されますか?
ここでまずクラスの継承を理解したいです.三つの属性、共有属性、私有属性、静的属性(Es 7)/静的類(Es 6)があります.
共有属性を継承:
function Parent(){
    this.name = 'parent';
}
new Parent();//this       
Parent() //this    window
function Child(){
    this.age = 9;
    Parent.call(this);//    this.name = 'parent' //      
}
親の属性を継承:
function Parent(){
    this.name = 'parent';
}
Parent.prototype.eat = function(){
    console.log('eat')
}
function Child(){
    this.age = 9;
    Parent.call(this);//    this.name = 'parent' //      
}
Child.prototype.smoking = function(){
    console.log('smoking')
}

Child.prototype = Parent.prototype;//      
//         Child.prototype    ,Parent.prototype           ,,
           
Child.prototype._proto_ = Parent.prototype //    
//object.create
Child.prototype = object.create(Parent.prototype); //   ,       
function create(parentPrototype,props){
    function Fn(){}
    Fn.prototype = parentPrototype;
    let fn = new Fn();
    for(let key in props){
        Object.defineProperty(fn,key,{
            ...props[key],
            enumerable:true
        });
    }
    return fn();
}
Child.prototype = create(Parent.prototype,{
    constructor: {
        value:Child
    }
})
共有属性とプライベート属性を継承:
これまでの継承は全部原型チェーンの継承です.聖杯モードはクラスで継承されていますが、何が違っていますか?ES 5での本当の継承はどうなりますか?
function Animal (weight, name) {
    this.name = name
    this.age = 0
    this.weight = 10
}
Animal.prototype.eat = function () {
    console.log('animal eat')
}
Animal.prototype.drink = function () {
    console.log('a d')
}
function Person(name, weight) {
    Animal.call(this, weight, name)
}
Person.prototype = Object.create(Animal.prototype)
Person.prototype.eat = function () {
    console.log('Person eat')
}
 var p = new Person('dxm', 70) 
ここには2つの点があります.
1父の構造関数はどうしてコールしますか?
2原型は書き換えが必要です.classで継承すると簡単になります.上記の例はクラスで実現します.
class Animal {
    constructor(name) {
        this.name = name
    }
    eat() {
        console.log('a e')
    }
    drink() {
        console.log('a d')
    }
}
class Person extends Animal {
    constructor(name) {
        super(name)
    }
    eat() {
        console.log('p e')
    }
}
ここで実現した後、2人の皆さんが知らないことが多くなりました.extends super extensの後に付いてくるのは私達が引き継ぐ内容です.
superの注意点類は派生類とも言われています.constructorでsuper関数を呼び出さなければなりません.thisは使えません.正確にはサブクラスはthisがないので、継承後は何も書かないで、デフォルトでも記入します.
class Person extends Animal {
    constructor(...arg) {
        super(...arg)    
    }
}
superを呼び出す前に、thisリターンsuperを使用してはいけません.オブジェクトとして使用できます.親タイプのプロトタイプsuperが親タイプの方法を呼び出すと、サブクラスのthisが結合されます.
クラスはnewしかできません
class Parent{
    //    
    constructor(){
        this.name = 'parent',
        this.age = '40'
    }
    //    ,      
    eat(){
        console.log('eat')
    }
    //    /   es6/es7
    //        Child.a()
    static b(){
        return 2
    }
}
new Parent();
class Child extends Parent{ //          
    //    
    constructor(){
        super() //     Parent.call(this)
        this.name = 'child'
    }
    //    ,      
    smoking(){
        console.log('smoking')
    }
    //    /   es6/es7
    //        Child.a()
    static a(){
        return 1
    }
}
let child = new Child();
console.log(child.name,child.age,child.eat(),child.smoking,Child.b())
//       ,     
//                 ,              this
まず作成クラスの関数を書きます.
//        new    
function _classCallCheck(instance,constructor){
    if(!(instance instanceof constructor)){
        throw new Error('Class constructor Child cannot be invoked without new')
    }
}

//constructor     
//prprotoPropertys       
//staticPropertys        
function definePropertys(target,arr){
    for(let i=0;i 0){
        definePropertys(constructor.prototype,protoPropertys)
    }
    if(staticPropertys.length > 0){
        definePropertys(constructor,staticPropertys)
    }
}
let Parent = function(){
    //   
    function P(){
        _classCallCheck(this,P)
        this.name = 'parent';
        //return {}
    }
    _createClass(P,//     
        [
            {
                key: 'eat',
                value: function () {
                    console.log(' ')
                }
            }
        ],
        [
            {
                key:'b',
                value:function () {
                    return 2;
                }
            }
        ]
    )
    return P;
}()
let p = new Parent();
console.log(p.eat())
これで私たちのクラスは作成されました.