2016-07-07 12 views
3

「クラス」がES5でどのように機能するのか、Javaのような従来型のオブジェクト指向言語の知識をどのようにJavaスクリプトに適用できるかを理解しようとしています。javascriptのクラスとアクセス修飾子

次のコードサンプルでは、​​私の質問にコメントしました。

var MyClass = (function() { 

    // [What am I?] A private variable? 
    var myVariable1 

    // Constructor. 
    function MyClass() { 
     // Essentially a public variable. 
     this.myVariable2 = 0; 
    } 

    // Public method returning myVariable1. 
    MyClass.prototype.myMethod1 = function() { 
     return myVariable1; 
    }; 

    // Public method returning public variable. 
    MyClass.prototype.myMethod2 = function() { 
     return this.myVariable2; 
    }; 

    // [What am I?] A private method? 
    function myMethod3() { 
     return 0; 
    } 

    return MyClass; 

}()); 

私は主に「私的な」ものについて疑問を抱いています。同様に、このクラスのインスタンスが複数あるとどうなりますか?彼らはお互いの私的な変数や機能に干渉することができますか?

+1

「Javaのような伝統的な型付きオブジェクト指向言語の知識を、JavaScriptに適用する方法」JavaScriptは静かではありません。別の考え方が必要です。 JSには「クラス」のものはありません(たとえES2015が存在するとしても)。「クラス」と呼ばれるものは、すべてのインスタンス間でプロパティとメソッドを共有できる呼び出し可能な動的オブジェクト(コンストラクタ関数)です。オブジェクトのプロトタイプが変更されると、すべてのインスタンスが影響を受けます。 –

答えて

4

まず私は、このビットに対応します:

...とどのように私はJavaScriptにJavaのような伝統的な、型指定されたオブジェクト指向言語の私の知識を適用することができます。

あなたが頻繁に。ビットのJava/C#の/ etcのようなもののJavaScriptの思考を離れて得ることができますが、あなたが行う場合は、A)JavaScriptがようではありませんので、いくつかの点であなたをかみますよJava/C#/ etcのように見えるようになっていますが、は基本的にです。 B)基本的に異なる性質をどのように使用するのか分からずに、JavaScriptの真のパワーを見逃してしまうでしょう。リモートから批判のあらゆる形態を意味するものではないこと(どのように私は知っていますか?私は、Javaから来た[さらにはC++]背景とJavaScriptは類似していたと仮定正確、をしました。)

、それだけの言葉です賢い。 JavaScriptのプロトタイプの継承とクロージャーがどのように機能するかを深く学び、問題を解決する方法はJava/C#/などのやり方とは多少異なるでしょう。インライン

回答:

var MyClass = (function() { 

    // [What am I?] A private variable? 
    // ==> A private *class* variable (static variable). Not instance-specific. 
    var myVariable1 

    // Constructor. 
    function MyClass() { 
     // Essentially a public variable. 
     // ==> A public field/property/variable, choose your terminology. :-) 
     // ==> The Java spec calls them both fields and variables (oddly). 
     // ==> In JavaScript, they're called properties. 
     this.myVariable2 = 0; 
    } 

    // Public method returning myVariable1. 
    // ==> Correct, but note that myVariable1 is shared across all instances 
    MyClass.prototype.myMethod1 = function() { 
     return myVariable1; 
    }; 

    // Public method returning public variable. 
    // ==> Yes, note that this one is returning an instance-specific field/property/variable 
    MyClass.prototype.myMethod2 = function() { 
     return this.myVariable2; 
    }; 

    // [What am I?] A private method? 
    // ==> A private *class* method (static method), yes. 
    function myMethod3() { 
     return 0; 
    } 

    return MyClass; 

}()); 

私は主に "プライベート" なものについて疑問に思って。同様に、このクラスのインスタンスが複数あるとどうなりますか?彼らはお互いの私的な変数や機能に干渉することができますか?

はい、コメントに記載されているとおり、クラス全体です。あなたはプライベート「インスタンスフィールド」を持っていると思った場合、あなたはあなたのコンストラクタ内にそれを宣言する必要があり、そして、彼らはそれの上に閉じたように、コンストラクタ内それへのアクセス権を持つために必要なすべての機能を作成したい:

function MyClass(arg) { 
    var privateInstanceInfo = arg; // We could also just use arg directly 

    this.accessThePrivateInstanceInfo = function() { 
     return privateInstanceInfo * 42; 
    }; 
} 
MyClass.prototype.useOnlyPublicInfo = function() { 
    // This cannot access `privateInstanceInfo` directly. 
    // It *can* access the function `accessThePrivateInstanceInfo` 
    // because that's public: 
    return accessThePrivateInstanceInfo(); 
}; 
var c = new MyClass(2); 
console.log(c.useOnlyPublicInfo()); // 84 

これで、すべてこの質問とその答えで詳細に概説されて閉鎖と呼ばれる概念にダウン:How do JavaScript closures work?私も数年前Closures are not complicatedから私の記事を参照します、それは物事のためにいくつかの古い用語を使用しながら、最新の仕様と比較しても、コンセプトはまだうまく説明されています。

ラッパーとして使用したインライン呼び出し関数(IIFE)は、その内部のすべての関数が終了する単一の実行コンテキストを作成します。つまり、関数が返っても、そのコンテキスト内で定義された変数と関数にライブアクセスできます。一度呼び出すだけなので、コンテキストは1つで、myVariable1myMethod3のいずれか1つのみです。私の例では

プライベートインスタンス情報を作成し、我々は新しいコンテキストをコンストラクタに各呼び出しのために作成されているという事実を使用しています。そのコンテキストは他のものと共有されないため、インスタンス固有になります。

ランダムに選択された名前を使用することである、コンストラクタ内の関数を定義することなく近く-privateインスタンスのプロパティを取得する方法があります:生命維持の内側

function makeRandomName() { 
    var str = ""; 
    while (str.length < 10) { 
     str += String.fromCharCode(32 + Math.floor(95 * Math.random())); 
    } 
    return "__" + str; 
} 
var MyClass = (function() { 
    var pseudoPrivatePropName = makeRandomName(); 

    function MyClass() { 
     this[pseudoPrivatePropName] = 42; 
    } 

    // .... 

    return MyClass; 
})(); 

コードが名前を知っていますそれ以外のコードはそうではありません。悪意のあるコードでもこのプロパティが見つかる可能性がありますが、特に複数のものがある場合は、さらに難しくなります。 (あなたが複数ある場合は、あなたは上記のものよりも優れた名アロケータを必要とする。)ES2015(ES6)で

あなたの代わりに名前アロケータを持つの...

var pseudoPrivatePropName = Symbol(); 

を使用することができます。

詳細はthis somewhat-outdated articleのブログにあります。

+1

あなたの精巧な答えをありがとう! – datcat

関連する問題