Nodejsノート--オブジェクトモデル

53456 ワード

JSオブジェクトモデル
JavaScriptは、クラスベースのオブジェクト向け言語ではなく、プロトタイプベースのオブジェクト向け言語です.C++、JavaにはクラスClassとインスタンスInstanceの概念があり、クラスは物事の抽象であり、インスタンスはクラスのエンティティである.JSはプロトタイプベースの言語で、プロトタイプオブジェクトの概念しかありません.プロトタイプオブジェクトはテンプレートであり、新しいオブジェクトはこのテンプレートから構築され、最初のプロパティを取得します.任意のオブジェクトは、実行時にプロパティを動的に追加できます.また、いずれのオブジェクトも別のオブジェクトのプロトタイプとして使用でき、後者は前者の属性を共有することができる.
クラスの定義
リテラル宣言方式
var obj = {
    x: 1,
    1: 'abc',
    "y": '123'
}

for (let x in obj)
    console.log(x, typeof x);

/*    :
1 string
x string
y string
*/

この方法は、フォント値作成オブジェクトと呼ばれます.
let a = 1, b = 2
let obj = {a, b}
let obj1 = {a: a, 'b': b} //       
console.log(obj)
console.log(obj1)

let c = 'str1'
let d = {
    c: 100, //   c    'c',        c
    [c]: 200 //     c  ,          
}
console.log(d)

/*    :
{ a: 1, b: 2 }
{ a: 1, b: 2 }
{ c: 100, str1: 200 }
*/

オブジェクトのキーキーは文字列タイプのみで、変数を使用する場合はカッコ[]で囲まれます.
ES 6以前のコンストラクタ
1、関数(コンストラクタ)オブジェクトを定義します.関数名の頭文字が大文字です.2、thisを使用して属性を定義します.3、newとコンストラクタを使用して新しいオブジェクトを作成します.
function Point(x, y) {
    this.x = x;
    this.y = y;
    this.show = () => console.log(this.x, this.y);
    console.log('Point ----')
}

p1 = new Point(3, 4)
console.log(p1)
console.log('--'.repeat(20))

function PointChild(x, y, z) {
    Point.call(this, x, y) //   
    this.z = z
    console.log('PointChild ---')
}

p2 = new PointChild(4, 5, 6)
console.log(p2)
p2.show()

/*    :
Point ----
Point { x: 3, y: 4, show: [Function] }
----------------------------------------
Point ----
PointChild ---
PointChild { x: 4, y: 5, show: [Function], z: 6 }
4 5
*/

新しいオブジェクトを構築するにはnewで構築する必要があります.クラスでベースクラスを呼び出すにはcallメソッドを使用します.サブクラスに転送できるthis注意:newキーワードを使用しない場合は、通常の関数呼び出しです.thisはインスタンスを表しません.
ES 6のclass
ES 6からclassキーワードが新たに提供され、オブジェクトの作成がより簡単で明確になります.1、クラス定義はclassキーワードを使用します.作成された本質的には関数であり、特殊な関数2であり、クラスにはconstructorというコンストラクタメソッドしかありません.構造メソッドを明示的に定義していない場合は、デフォルトのconstuctorメソッドが追加されます.3、継承extendsキーワード4、1つのコンストラクタはsuperキーワードを使用して1つの親クラスのコンストラクタ5を呼び出すことができ、クラスにはプライベート属性がない
class Point {
    constructor(x, y){ //    
        this.x = x;
        this.y = y;
    }
    show() { //  
        console.log(this, this.x, this.y);
    }
}
p1 = new Point(2,3);
console.log(p1);
p1.show(); // this  p1      ,   python self

//  
class PointChild extends Point {
    constructor(x, y, z) {
        super(x, y); //    super
        this.z = z;
    }
}
p2 = new PointChild(4, 6, 8);
console.log(p2);
p2.show();

/*    :
Point { x: 2, y: 3 }
Point { x: 2, y: 3 } 2 3
PointChild { x: 4, y: 6, z: 8 }
PointChild { x: 4, y: 6, z: 8 } 4 6
*/

newを使用してオブジェクトを構築し、クラスを継承する場合は、属性が定義されていない前に必ずsuperメソッドでベースクラスを呼び出します.
書き換え方法
サブクラスPointChildのshowメソッドは書き換える必要があります
class Point {
    constructor(x, y){ //    
        this.x = x;
        this.y = y;
    }
    show() { //  
        console.log(this, this.x, this.y);
    }
}
p1 = new Point(2,3)
console.log(p1)
p1.show() // this  p1      ,   python self

//  
class PointChild extends Point {
    constructor(x, y, z) {
        super(x, y); //    super
        this.z = z;
    }
    show() { //     
        console.log(this, this.x, this.y, this.z);
    }
}
p2 = new PointChild(4, 6, 8)
console.log(p2)
p2.show()

/*    :
Point { x: 2, y: 3 }
Point { x: 2, y: 3 } 2 3
PointChild { x: 4, y: 6, z: 8 }
PointChild { x: 4, y: 6, z: 8 } 4 6 8
*/

子クラスで親クラスを直接書き換える方法です.親クラスのメソッドを使用する必要がある場合はsuper.method()で呼び出します.
矢印関数を使用してメソッドを定義することもできます.
class Point {
    constructor(x, y){ //    
        this.x = x;
        this.y = y;
        this.show = () => console.log('Point ---'); //         
    }
}
p1 = new Point(2,3)
p1.show() // this  p1      ,   python self

//  
class PointChild extends Point {
    constructor(x, y, z) {
        super(x, y); //    super
        this.z = z;
        this.show = () => console.log('PointChild ---');
    }
}
p2 = new PointChild(4, 6, 8)
p2.show()

/*    :
Point ---
PointChild ---
*/

実行結果から、矢印関数はサブクラスがベースクラスを上書きする方法もサポートします.
class Point {
    constructor(x, y){ //    
        this.x = x;
        this.y = y;
        this.show = () => console.log('Point ---');
    }
}
p1 = new Point(2,3)
p1.show() // this  p1      ,   python self

//  
class PointChild extends Point {
    constructor(x, y, z) {
        super(x, y); //    super
        this.z = z;
    }
    show() { //     
        console.log(this, this.x, this.y, this.z);
    }
}
p2 = new PointChild(4, 6, 8)
p2.show()

/*    :
Point ---
Point ---
*/

前例の親は矢印関数でメソッドを定義し,子は一般関数でメソッドを定義し,実行結果から親のshowメソッドを優先的に使用した.
class Point {
    constructor(x, y){ //    
        this.x = x;
        this.y = y;
    }
    show() {
        console.log(this, this.x, this.y);
    }
}
p1 = new Point(2,3)
p1.show() // this  p1      ,   python self

//  
class PointChild extends Point {
    constructor(x, y, z) {
        super(x, y); //    super
        this.z = z;
        this.show = () => console.log('PointChild ---');
    }
}
p2 = new PointChild(4, 6, 8)
p2.show()

/*    :
Point ---
PointChild ---
*/

前例の親は一般関数定義メソッド,子は矢印関数定義メソッドを用い,実行結果から子クラスのshowメソッドを優先的に用いた.
まとめ:親、子は同じ方法でクラス定義属性またはメソッドを使用し、子は親を上書きします.同じ名前のプロパティまたはメソッドにアクセスする場合は、プロパティ矢印関数を使用してインスタンスのプロパティに定義し、通常の関数をクラスのメソッドに定義し、プロパティをメソッドに優先します.
スタティツクメソッド
メソッド名にstaticを付けると、静的メソッドになります
class Add {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    static print() {
        console.log('static method', this.x)
    }
}

add = new Add(3, 5)
console.log(Add)
// add.print() //               , C++、Java  
Add.print()
add.constructor.print() //       constructor      

/*    :
[Function: Add]
static method undefined
static method undefined
*/

静的メソッドのthisは、AddのインスタンスではなくAddクラスです.
注意:静的概念はPythonの静的と異なり、Pythonのクラス変数に相当する.
この穴
JsはC++、Javaと同じようにthisがありますが、Jsの表現は違います.なぜなら、C++、Javaは静的コンパイル言語であり、thisはコンパイル期間バインディングであり、Jsは動的言語であり、実行期間バインディングである
var school = {
    name: 'school',
    getNameFunc:function () {
        console.log(this.name);
        console.log(this);
        return function () {
            console.log(this === global); // this   global  
            return this.name;
        };
    }
};
console.log(school.getNameFunc()());

/*    :
school
{ name: 'school', getNameFunc: [Function: getNameFunc] }
true
undefined
*/

関数を実行すると、新しい実行コンテキスト環境ExecutionContextが開きます.thisプロパティを作成しますが、thisが何であるかは関数がどのように呼び出されているかによって決まります.1、myFunction(1,2,3)、通常の関数呼び出し方式で、これはグローバルオブジェクトを指します.グローバルオブジェクトはnodejsのglobalまたはブラウザのwindowです.2、myobject.myFunction(1,2,3)は、メソッドを含むオブジェクトを指すオブジェクトメソッドの呼び出し方法である.3、call、apply、bindメソッド呼び出しの場合、最初のパラメータが誰であるかを見ます.
前例:school{ name: 'school', getNameFunc: [Function: getNameFunc] }を分析してよく理解した.3行目に印刷されたtrueは、console.log(this === global)で実行された結果であり、現在globalであることを示している.この返された関数を呼び出すのは直接呼び出され、これは通常の関数呼び出しであるため、thisはグローバルオブジェクトである.4行目undefinedは、thisがglobalでname属性がないためです.
入力の表示
var school = {
    name: 'school',
    getNameFunc:function () {
        console.log(this.name);
        console.log(this);
        return function (that) {
            console.log(this === global); // this   global  
            return that.name;
        };
    }
};
console.log(school.getNameFunc()(school));

/*    :
school
{ name: 'school', getNameFunc: [Function: getNameFunc] }
true
school
*/

アクティブにオブジェクトを転送することで、thisの問題を回避できます.
apply、callメソッド
var school = {
    name: 'school',
    getNameFunc:function () {
        console.log(this.name);
        console.log(this);
        return function () {
            console.log(this === global); // this   global  
            return this.name;
        };
    }
};
console.log(school.getNameFunc().call(school)); // call      this     

/*    :
school
{ name: 'school', getNameFunc: [Function: getNameFunc] }
false
school
*/

apply,callメソッドはいずれも関数オブジェクトのメソッドであり,第1のパラメータはいずれも入力オブジェクトによって導入される.apply伝達他のパラメータ配列call伝達他のパラメータ伝達可変パラメータ収集
function Point(x, y){
    this.x = x;
    this.y = y;
    console.log(this === global);
    console.log('Point ----');
}

p1 = Point(3, 4);
console.log(p1);
console.log('--'.repeat(20))

p2 = new Object();
console.log(p2);

p3 = Point.call(p2, 10, 11);
// p3 = Point.apply(p2, [10, 11]);
console.log(p3);
console.log(p2);

/*    :
true
Point ----
undefined
----------------------------------------
{}
false
Point ----
undefined
{ x: 10, y: 11 }
*/
p1 = Point(3, 4);p3 = Point.call(p2, 10, 11);はnewメソッドでオブジェクトを構築する、通常の関数呼び出しとしか言えず、Pointには戻り値がないため、p 1とp 3はいずれもundefined p3 = Point.call(p2, 10, 11);であり、callメソッドでは、入力p 2が関数であるthisオブジェクトが表示する、関数内には、そのオブジェクトにx,y属性が注入される.
bindメソッド
var school = {
    name: 'school',
    getNameFunc:function () {
        console.log(this.name);
        console.log(this);
        return function () {
            console.log(this === global); // this   global  
            return this.name;
        };
    }
};
var boundfunc = school.getNameFunc().bind(school); // bind           
console.log(boundfunc);
console.log(boundfunc());

/*    :
school
{ name: 'school', getNameFunc: [Function: getNameFunc] }
[Function: bound ]
false
school
*/

bindメソッドはapply、callメソッドとは異なり、関数のためにthisを先にバインドし、新しい関数を返し、呼び出すときに直接使用する.apply、callメソッドはすべて呼び出すときにthisに伝わる.
ES 6はthisをサポートする矢印関数を導入する
ES 6の新技術は、この問題に対応する必要はありません.
var school = {
    name: 'school',
    getNameFunc:function () {
        console.log(this.name);
        console.log(this);
        return () => {
            console.log(this === global); // this   global  
            return this.name;
        };
    }
};
console.log(school.getNameFunc()());

/*    :
school
{ name: 'school', getNameFunc: [Function: getNameFunc] }
false
school
*/