ホームページ  >  記事  >  ウェブフロントエンド  >  ES6におけるプライベート変数の実装概要(コード例)

ES6におけるプライベート変数の実装概要(コード例)

不言
不言転載
2018-11-21 11:25:491671ブラウズ

この記事は、ES6 でのプライベート変数の実装 (コード例) をまとめたものです。必要な方は参考にしていただければ幸いです。

「ECMAScript 6 入門」を読んでいると、プライベート変数の実装が散見されたので、ここにまとめておきます。

1. 同意事項

実装

class Example {
    constructor() {
        this._private = 'private';
    }
    getName() {
        return this._private
    }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // private

メリット

  1. 簡単な書き方

  2. # # 簡単なデバッグ

  3. 優れた互換性

欠点

  1. 外部アクセスと変更

  2. この言語には一致するメカニズムがありません。たとえば、for in ステートメントはすべての属性を列挙します

  3. ##名前の競合
  4. 2. まとめ

/**
 * 实现一
 */
class Example {
  constructor() {
    var _private = '';
    _private = 'private';
    this.getName = function() {return _private}
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined

の実装による利点

    名前の競合がない
  1. ##外部アクセスおよび変更ができない

  2. デメリット

コンストラクタのロジックが複雑になります。コンストラクターはオブジェクトの初期化のみを実行する必要がありますが、プライベート変数を実装するには、いくつかのメソッドの実装を含める必要があり、コード構成は若干不明確です。

  1. メソッドはプロトタイプではなくインスタンスに存在し、サブクラスはスーパーを使用して呼び出すことができません。

  2. 構築により若干のオーバーヘッドが追加されます

  3. #実装 2

    /**
     * 实现二
     */
    const Example = (function() {
      var _private = '';
    
      class Example {
        constructor() {
          _private = 'private';
        }
        getName() {
          return _private;
        }
      }
    
      return Example;
    
    })();
    
    var ex = new Example();
    
    console.log(ex.getName()); // private
    console.log(ex._private); // undefined
    利点

名前の競合がない

  1. 外部からアクセスおよび変更できない

  2. デメリット

記述方法が少し複雑

    ##構築により若干のオーバーヘッドが発生します
  1. 3. シンボル
  2. 実装

    const Example = (function() {
        var _private = Symbol('private');
    
        class Example {
            constructor() {
              this[_private] = 'private';
            }
            getName() {
              return this[_private];
            }
        }
    
        return Example;
    })();
    
    var ex = new Example();
    
    console.log(ex.getName()); // private
    console.log(ex.name); // undefined
  3. 利点

名前の競合なし

  1. 外部からアクセスしたり変更したりすることはできません

  2. パフォーマンスの低下はありません

  3. 欠点

##少し複雑な記述

  1. 互換性も良好です

  2. 4。WeakMap

    実装
  3. /**
     * 实现一
     */
    const _private = new WeakMap();
    
    class Example {
      constructor() {
        _private.set(this, 'private');
      }
      getName() {
          return _private.get(this);
      }
    }
    
    var ex = new Example();
    
    console.log(ex.getName()); // private
    console.log(ex.name); // undefined
このように書くとカプセル化が不十分だと感じるかもしれませんが、次のように書くこともできます:

/**
 * 实现二
 */
const Example = (function() {
  var _private = new WeakMap(); // 私有成员存储容器

  class Example {
    constructor() {
      _private.set(this, 'private');
    }
    getName() {
        return _private.get(this);
    }
  }

  return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

利点

名前の競合がない

  1. 外部にアクセスして変更できない

  2. ##欠点
  3. ##書くのがさらに面倒

##互換性には少し問題があります

  1. パフォーマンスに一定のコストがかかります

  2. ##5 最新の提案

    #

    class Point {
      #x;
      #y;
    
      constructor(x, y) {
        this.#x = x;
        this.#y = y;
      }
    
      equals(point) {
        return this.#x === point.#x && this.#y === point.#y;
      }
    }
    #。 ##それでは、プライベート フィールドを直接使用しないのはなぜでしょうか?例:
    class Foo {
      private value;
    
      equals(foo) {
        return this.value === foo.value;
      }
    }
  3. 簡単に言うと、面倒ですし、もちろんパフォーマンス上の考慮事項もあります...
  4. たとえば、# を使用せずに、private を使用するとします。キーワード :

    class Foo {
      private value = '1';
    
      equals(foo) {
        return this.value === foo.value;
      }
    }
    
    var foo1 = new Foo();
    var foo2 = new Foo();
    
    console.log(foo1.equals(foo2));
  5. ここでは、2 つの新しいインスタンスを作成し、foo2 をパラメータとして foo1 のインスタンス メソッドに渡します。

それでは、foo2.value の値を取得できますか?

foo2.value

を直接実行すると、値は絶対に取得できません。結局、プライベート変数ですが、equals は Foo のクラスメソッドなので、取得できるでしょうか。

答えは「はい」です。

実際、これは Java や C などの他の言語でも同じです。

クラスのメンバー関数は、同じ型のインスタンスのプライベート変数にアクセスできます。これは、プライベート性があるためです。実装の場合、「外部」情報はクラス自体の中に隠蔽されます。プライベート変数へのアクセスを禁止する必要はありません。さらに、これはオブジェクトではなくクラスに基づいていることも理解できます。ユーザーにBringの利便性を提供します。

値を取得できるため、出力された結果は true になるはずですが、渡した値が Foo のインスタンスではなく、別のオブジェクトの場合はどうなるでしょうか。

var foo1 = new Foo();

console.log(foo1.equals({
  value: 2
}));
もちろん、ここのコードは正常に実行できますが、コンパイラにとっては少し面倒です。コンパイラは、value が通常のプロパティであるか foo のプライベート プロパティであるかを認識しないため、コンパイラは判定を行うには、まず foo が Foo のインスタンスであるかどうかを判断し、次に値を取得します。 これは、属性アクセスごとにそのような判断を行う必要があり、エンジンは属性アクセスを中心に高度に最適化されているため、変更が非常に遅く、速度も低下することも意味します。

ただし、この作業に加えて、次のような考慮すべき点がいくつかあります。

秘密キーを各字句環境にエンコードする必要があります

for in これらのプロパティを通過できますか?

プライベート属性と通常の属性が同じ名前を持つ場合、誰が誰をブロックするのでしょうか?
  1. プライベート属性の名前が検出されないようにする方法。
  2. プライベートの代わりに # を使用する方法について詳しくは、この問題を参照してください。
  3. もちろん、これらの問題は解決できますが、少し面倒です。

    # を選択すると、実装メソッドは
  4. private スロット
  5. メソッドを使用し、新しいスロット検索構文を使用します。 private の実装ははるかに簡単です。

以上がES6におけるプライベート変数の実装概要(コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。