対象に向けるJavaScript――クラス


javaではクラスを定義する時に使うのはクラスのキーワードですが、JavaScriptではクラスは単語を保留しています。また用途がありますので、他の方法でJavaScriptのクラスを定義します。
クラスを定義
JavaScriptのfunctionのキーワードを利用して、クラス名の頭文字は普通大文字を採用します。
function Person(id,name,age){
    this.id = id;
    this.name = name;
    this.age = age;
}
javaのクラスを回想すると、このクラスと同名のコンストラクタがあります。開発者自身が書いていなくても、java仮想マシンは標準のコンストラクタを与えます。JavaScriptここでは、上のこのタイプ自体も実は構造関数です。ここで一言を覚えてください。
「コンストラクタは対象のクラスに名前を与え、属性を初期化する」という方法を使います。
var per = new Person("001","Xiao Wei","12");
上記のコンストラクタのthisポインタ(厳密にはthisは指針ではなく、ポインタとして考えているだけで分かりやすいです。)が指す変数はPerson類のデータメンバー(または属性といいます。)で、アクセス権限はpublicです。javaのクラスには属性がある以外に方法があります。以下はJavaScript類に関数を追加します。
function Person(id,name,age){
    this.id = id;
    this.name = name;
    this.age = age;
    this.getInformation = function(){
        return "  :"+this.id+";  :"+this.name+";  :"+this.age;
    };
}
上記は最も直接的な方法でクラスに属性を追加しますが、これは良い方法ではないです。客観的な事物の説明が正しくないからです。属性は各インスタンス(つまりオブジェクト)に一つずつあります。方法は必要ではないはずです。方法はデータを処理するために共用されているので、より良い解決方法はprototype原型方式を採用しています。
function Person(id,name,age){
    this.id = id;
    this.name = name;
    this.age = age;
}
Person.prototype.getInformation = function(){
    return "  :"+this.id+";  :"+this.name+";  :"+this.age;
};
ここで原型の方式を採用できるのは
JavaScriptオブジェクトごとにプロトタイプオブジェクトの内部参照が含まれています。実は方法だけでなく、属性もプロトタイプの原型方式を採用することができます。ここでもう一つの言葉を覚えます。
「方法とその他の不変属性は原型の対象に置く。」
クラスはすでにfunctionキーワードによって実現されました。これは一つの実現方式です。このような方式は簡単で分かりやすいです。実はもう一つの実現方法があります。実現するのはとても優雅です。私達は下記のコードを見ます。
var Class={
    create:function(){
        return function(){
            this.inital.apply(this,arguments);
        };
    }
};
/*  Person */
var Person=Class.create();
Person.prototype={
    inital:function(id,name,age){
        this.id = id;
        this.name = name;
        this.age = age;
    },
    getInformation:function(){
        return "  :"+this.id+";  :"+this.name+";  :"+this.age;
    }
};
キーコードは、this.inital.apply(this,argments)である。このような行は、Class自体がオブジェクトであり、createという方法があります。この方法は関数ポインタを返します。この方法は、関数の内部でthis.inital.appyを実行します。thisは現在のオブジェクトを指しています。ここでPersonです。apply方法はinitial方法のスコープを変更します。argmentsはパラメータリストです。appyについてもっと詳しく説明すると、私の前の学習ノート「JavaScript中call()とappy()の違いは何ですか?」を参照してください。
this
thisの詳細な使い方については読書ノート「JavaScriptの中のthisはどのように使うか」に紹介されています。ここはもう少しくどいです。
JavaScriptには、厳密に対象に向けた概念はなく、自然にもクラスの構造関数という概念はない。var o=new Obj();このような文法はJava/C++とかなり似ているように見えるが、その背後の実行過程は違っている。まず、解凍器はnewの空いているObjectのオブジェクトがあります。そしてこの空のObjectを、隠しパラメータとしてfunction Obj()に渡す。Obj関数でアクセスしたthisは、この入力された空のObjectオブジェクトです。これは、「thisキーワードは実行時の作用領域に関連する」という意味です。
関数を「コンストラクター」としたいなら、関数の最後にreturn文を加えないでください。return文がないとnew演算子が返ってくるのは、それが操作された後のthisですから。一旦リセットして他のものに戻ったら、このthisは廃棄されます。
匿名クラス
var class1 = {p1:value1,p2:value2};
これも書き上げられます。
var class1 = {};
class1.p1 = value1;
class1.p2 = value2;
まずすべての匿名クラスはObjectのコアオブジェクトに継承されており、var clast 1={}はObjectオブジェクトを実装することを意味し、Objectオブジェクトの元の属性と元の方法を持つ。しかし、匿名クラスに生の方法を追加することはできません。例えば、このように書くのは間違いです。
class1.prototype.func1 = function(){};
あなたもnew()の方法で新しいclass 1と同じ属性の新しいオブジェクトを構築してみることはできません。これはすでに実用化されています。以下の書き方も間違っています。
var classB = new classA();
これは構築できないもので、
正確には、匿名クラスは、実際にはObjectのあるインスタンスを継承しており、Cリキッドクラスに相当する。方法と属性を追加できます。たとえば:
class1.func1 = function(){};
呼び出し時はこのままです。
class1.func1();  //  C#     
しかし、Objectに原生関数を追加することができます。このようにあなたの匿名クラス(実際にはすべてのクラス)にはこの方法があります。たとえば:
var class1 = {};
class1.p1 = value1;
class1.p2 = value2;
Object.prototype.func1 = function(){ alert("1") };
class1.func1();
問題はないですが、このようにすると、すべての実用化対象にfunc 1()の方法があります。実際の応用ではObject類に原生方法を追加することは避けなければならない。
匿名関数
まずJavascriptの関数について説明します。JavaScriptの中ではすべて対象です。functionはもちろん例外ではありません。functionは関数としてもいいし、種類も関数の対象として返してもいいです。
次の例を見てください。
function a(){
    alert("Hello Febird!");
    this.aa = "aa";
    this.show = function(){
        alert(this.aa);
    };
    this.sayHello = function(){
        return function(){alert("hello");};
    };
}

var aaa = new a();
aaa.show();
aaa.sayHello();
その中の一番外の一つのfunctionはクラスaを定義しています。これは属性aaを持っています。方法ショー()、sayHello()。これらはいずれも匿名関数ですが、sayHelloのfunctionは戻り値として関数の例です。
実際には、匿名関数とは、名前が付いていないブロックのことであり、他の変数に値を付与すると、その変数は関数であり、正確には関数ポインタである。
JavaSriptでは匿名関数が特徴的なものであり、非常に有用であり、理解しにくいものでもあります。
例えば、Ajax引用を書く時、他のJSFに頼らないで、自分で共通のAjaxを書いたら、こう書きます。
var xhr = new XMLHttpRequest(); //    ,          ;
function DoAjax(){
    xhr.onreadystatechange=processFunction;
    xhr.open("GET",url,true);
    xhr.send(null);
}
function processFunction(){
    //do something with XMLHttpRequest;
    if(xhr.readState!=4||xhr.status!=200) return false;
    alert(xhr.responseText);
}
一般的なAjax引用では、XMLHttpRequestオブジェクトだけでなく、オンレディズステージの処理関数にパラメータがないとエラーが発生します。だから、大域変数XMLtHttpRequestを書いてプロモーションでこの大域変数を使いますが、もしいくつかのXMHttpRequestを作ったらどうなりますか?これはグローバル変数では使えませんが、処理関数にパラメータがありません。どうすればいいですか? 
function DoAjax(){
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = processFunction(xhr);
    xhr.open("GET",url,true);
    xhr.send(null);
}
function processFunction(_xhr){
    return function(){
        //do something with XMLHttpRequest;
        if(_xhr.readState!=4||_xhr.status!=200) return false;
        alert(_xhr.responseText);
    };
}
どう分かりますか?プロcessFunction関数にはパラメータがありますが、戻りの関数にはパラメータがありません。この二つの関数の間では、どのように値を伝達しますか?
ここで引用してもいいです。
関数を正確に実行するためには、関数によって使用される必要があります。ワードスコープ内の、大域データではなく、関数のクローズドに存在します。
このように理解できます。
プロcessFunction()を返す関数は、プロcessFunction以外で使用する場合、依然として自分が定義された時の上位作用領域における各種変数の値を覚えておく必要があります。これらの記憶すべき値は、「クローズド」です。
もとのままのオブジェクト
オリジナル、つまりプロトタイプは、元のオブジェクトを拡張し、改造する方法を提供します。例えば、JavaScriptのコアオブジェクトAray、Number、Math、Object、Booleanなどの既知のオブジェクトとカスタムクラスの追加方法または属性を含むことができます。
たとえば:
Number.prototype.toHexString = function () {
    return this.toString(16);
};
var num = 10;
alert(num.toHexString());
出力A;
この方法はObjectオブジェクトに追加できます。これからはどのオブジェクトにもこの方法があります。他のオブジェクトはすべてObjectから継承されます。
既存の関数を再構築することもできます。
Function.prototype.toString = function () {
    return “Function Locked”;
};
 
参考資料:
1. javascript実現類、継承、多態(オリジナル)
2. JavaScriptは対象に向かっています。