私は今、ES 6の機能を活用するためにTraceur Compilerを使用しています。
私はES5からこのものを実装したいです。
function Animal() {
var self = this,
sayHi;
sayHi = function() {
self.hi();
};
this.hi = function() {/* ... */}
}
現在traceurはprivate
name__およびpublic
name__キーワードをサポートしていません( Harmony から)。また、ES6クラス構文では、クラス本体で単純なvar
name__(またはlet
name__)ステートメントを使用することはできません。
私が見つける唯一の方法は、クラス宣言の前にprivatesをシミュレートすることです。何かのようなもの:
var sayHi = function() {
// ... do stuff
};
class Animal {
...
それは何よりも良いことではありませんが、期待どおりにthis
name__またはapply
nameなしで正しいbind
name__をprivateメソッドに渡すことはできません。
それでは、traceurコンパイラと互換性のあるES6クラスでプライベートデータを使用する可能性はありますか?
Current ECMAScript 6仕様書 には、private
、public
、またはprotected
キーワードはありません。
したがってTraceurはprivate
とpublic
をサポートしません。 6to5(現在は "Babel"と呼ばれています)は実験的な目的で この提案 を実現しています( この説明を参照 )。しかし、それは単なる提案です。
そのため、今のところWeakMap
を使ってプライベートプロパティをシミュレートすることができます( here を参照)。もう1つの選択肢はSymbol
です - しかし、プロパティはObject.getOwnPropertySymbols
を通して簡単にアクセスできるので実際のプライバシーを提供しません。
私見、現時点での最良の解決策 - 疑似プライバシーを使用してください。このメソッドでapply
またはcall
を頻繁に使用する場合、このメソッドは非常にオブジェクト固有のものです。それで、アンダースコアの接頭辞を付けて、あなたのクラスでそれを宣言することは価値があります:
class Animal {
_sayHi() {
// do stuff
}
}
通常の機能はいつでも使用できます。
function myPrivateFunction() {
console.log("My property: " + this.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
myPrivateFunction.bind(this)();
}
}
new MyClass(); // 'My property: myProp'
現時点では、メソッドやプロパティをプライベートとして宣言する方法はありませんが、ES6モジュールはグローバル名前空間にはありません。したがって、自分のモジュールで宣言してエクスポートしないものは、プログラムの他の部分では利用できませんが、それでも利用できます。実行時にモジュール。したがって、あなたはプライベートなプロパティとメソッドを持っています:)
以下はその例です(test.js
ファイル内)
function tryMe1(a) {
console.log(a + 2);
}
var tryMe2 = 1234;
class myModule {
tryMe3(a) {
console.log(a + 100);
}
getTryMe1(a) {
tryMe1(a);
}
getTryMe2() {
return tryMe2;
}
}
// Exports just myModule class. Not anything outside of it.
export default myModule;
別のファイルに
import MyModule from './test';
let bar = new MyModule();
tryMe1(1); // ReferenceError: tryMe1 is not defined
tryMe2; // ReferenceError: tryMe2 is not defined
bar.tryMe1(1); // TypeError: bar.tryMe1 is not a function
bar.tryMe2; // undefined
bar.tryMe3(1); // 101
bar.getTryMe1(1); // 3
bar.getTryMe2(); // 1234
あなたはシンボルを使用することができます
var say = Symbol()
function Cat(){
this[say]() // call private methos
}
Cat.prototype[say] = function(){ alert('im a private') }
P.Sアレックスポッドは正しくありません。継承は名前の衝突であるため、彼は非公開よりも保護を受けます
実際には代わりにvar say = String(Math.random())
を使うことができますSymbol
ES6の場合:
var say = Symbol()
class Cat {
constructor(){
this[say]() // call private
}
[say](){
alert('im private')
}
}
これが役に立つことを願っています。 :)
I. var、宣言中の関数 IIFE(即時呼び出し関数式) を宣言すると、これらは無名関数でのみ使用できます。 (ES6用にコードを変更する必要がある場合は、 'var'を使用せずに "let、const"キーワードを使用することをお勧めします。)
let Name = (function() {
const _privateHello = function() {
}
class Name {
constructor() {
}
publicMethod() {
_privateHello()
}
}
return Name;
})();
II。 WeakMapオブジェクトはメモリリークのトラブルに良いでしょう。
インスタンスが削除されると、WeakMapに格納されている変数は削除されます。この記事をチェックしてください。 ( ES6クラスのプライベートデータの管理 )
let Name = (function() {
const _privateName = new WeakMap();
})();
III。全部まとめてみましょう。
let Name = (function() {
const _privateName = new WeakMap();
const _privateHello = function(fullName) {
console.log("Hello, " + fullName);
}
class Name {
constructor(firstName, lastName) {
_privateName.set(this, {firstName: firstName, lastName: lastName});
}
static printName(name) {
let privateName = _privateName.get(name);
let _fullname = privateName.firstName + " " + privateName.lastName;
_privateHello(_fullname);
}
printName() {
let privateName = _privateName.get(this);
let _fullname = privateName.firstName + " " + privateName.lastName;
_privateHello(_fullname);
}
}
return Name;
})();
var aMan = new Name("JH", "Son");
aMan.printName(); // "Hello, JH Son"
Name.printName(aMan); // "Hello, JH Son"
アレックスポッドが言うように、ES6ではこれを行うための専用の方法はありません。しかし、興味のある人のために、この種の構文を有効にする バインド演算子 の提案もあります。
function privateMethod() {
return `Hello ${this.name}`;
}
export class Animal {
constructor(name) {
this.name = name;
}
publicMethod() {
this::privateMethod();
}
}
繰り返しますが、これは単なる提案です。あなたのマイレージは異なる場合があります。
ファクトリー機能の使用を検討しましたか?通常、これらは JavaScriptまたはクラスのコンストラクタ関数に代わるはるかに優れた代替手段 です。これがどのように機能するかの例は、次のとおりです。
function car () {
var privateVariable = 4
function privateFunction () {}
return {
color: 'red',
drive: function (miles) {},
stop: function() {}
....
}
}
クロージャのおかげで、返されたオブジェクト内のすべてのプライベート関数と変数ラベルにアクセスできますが、外部からそれらにアクセスすることはできません。
Marcelo Lazaroni はすでに言ったように、
現在、メソッドやプロパティをプライベートとして宣言する方法はありませんが、ES6モジュールはグローバル名前空間にはありません。したがって、モジュール内で宣言してエクスポートしないものは、プログラムの他の部分では使用できませんが、実行時にはまだモジュールで使用できます。
しかし彼の例は、プライベートメソッドがクラスのインスタンスのメンバーにどのようにアクセスできるかを示していません。 Max は、バインディングや、コンストラクタでラムダメソッドを使用する代替方法によるインスタンスメンバーへのアクセス方法の良い例を示していますが、追加したいと思いますもっと簡単な方法は、インスタンスをパラメータとしてプライベートメソッドに渡すことです。このようにすると、MaxのMyClassは次のようになります。
function myPrivateFunction(myClass) {
console.log("My property: " + myClass.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
}
testMethod() {
myPrivateFunction(this);
}
}
module.exports = MyClass;
どちらを選択するかは、実際には個人の好みによって決まります。
私は次のことを可能にするはるかに優れた解決策であると感じるものを思いつきました。
'this._'、その/ self、weakmaps、シンボルなどは必要ありません。明確でわかりやすい 'class'コード
プライベート変数とメソッドは本当にプライベートで、正しい 'this'バインディングを持ちます
'this'はまったく使用されていません。これは、エラーが発生しにくい、明確なコードを意味します。
パブリックインタフェースは明確で、プライベートメソッドへのプロキシとしての実装からは分離されています
簡単な合成が可能
これであなたはできる:
function Counter() {
// public interface
const proxy = {
advance, // advance counter and get new value
reset, // reset value
value // get value
}
// private variables and methods
let count=0;
function advance() {
return ++count;
}
function reset(newCount) {
count=(newCount || 0);
}
function value() {
return count;
}
return proxy;
}
let counter=Counter.New();
console.log(counter instanceof Counter); // true
counter.reset(100);
console.log('Counter next = '+counter.advance()); // 101
console.log(Object.getOwnPropertyNames(counter)); // ["advance", "reset", "value"]
<script src="https://cdn.rawgit.com/kofifus/New/7987670c/new.js"></script>
コードと、コンストラクタや合成を含むより複雑な例については、 新しい を参照してください。