JavaScript はカプセル化を使用します

高洛峰
リリース: 2016-11-30 16:59:45
オリジナル
971 人が閲覧しました

基本的なカプセル化方法

次の例を参照してください:

var Person = function(name,age){
  this.name = name;
  this.age = age || "未填写";
  this.hobbys = [];
}

Person.prototype = {
  sayName:function(){
    console.log(this.name);
  },
  sayAge:function(){
    console.log(this.age);
  },
  addHobby:function(hobbys){
    this.hobbys = this.hobbys.concat(hobbys);
  }
}

var person1 = new Person("Jane","20");
var person2 = new Person("TabWeng","21");

person1.addHobby(['sing','drawing']);
person2.addHobby(['football','study','running']);

person1.sayName();
console.log(person1.hobbys.toString());

person2.sayName();
console.log(person2.hobbys.toString());
ログイン後にコピー

動作結果:

Jane
歌う、絵を描く
TabWeng
フットボール、勉強、走る

これは、JavaScript オブジェクトの作成で説明されています。共有およびメソッドはプロトタイプに記述され、各インスタンスに独自のコピーを持つ必要があるプロパティとメソッドはコンストラクターに配置されます。

入力名に数字を含めることができないという問題が発生しました。解決策は、名前をチェックする関数を作成し、この関数をプロトタイプに記述することです。

var Person = function(name,age){
  //校验名称
  if(this.checkName(name)){
    throw new Error("名字 "+name+" 不能存在数字");
  }
  this.name = name;
  this.age = age || "未填写";
  this.hobbys = [];
}

Person.prototype = {
  //校验函数
  checkName:function(name){
    re = /\d/;
    return re.test(name);
  },
  sayName:function(){
    console.log(this.name);
  },
  sayAge:function(){
    console.log(this.age);
  },
  addHobby:function(hobbys){
    this.hobbys = this.hobbys.concat(hobbys);
  }
}

var person1 = new Person("Helen666","20");
var person2 = new Person("TabWeng","21");

person1.addHobby(['sing','drawing']);
person2.addHobby(['football','study','running']);

person1.sayName();
console.log(person1.hobbys.toString());

person2.sayName();
console.log(person2.hobbys.toString());
ログイン後にコピー

このコードでは、名前を検証するために checkName() 関数を作成しました。今のところ、数値が存在できないことを確認したいだけです。次に、コンストラクターのコードの最初の行でそれを検証します。検証が失敗し、合格した場合は例外がスローされます。
ここで Helen666 という名前を渡しましたが、次の例外がスローされました:

エラー: 名前 Helen666 には数字を含めることはできません

これにより、基本的なカプセル化が実現され、内部検証が実装されます。

しかし、次のように名前を定義することもできます:

var person1 = new Person("Helen","20");
person1.name = "Helen666";
person1.sayName(); //Helen666
ログイン後にコピー

名前は依然として不正な名前に変更できるため、制御に get メソッドと set メソッドを使用することを考えました。 set メソッドを通じてのみ割り当てられ、set メソッドを通じて検証し、get メソッドを通じて値を取得します。現在のコードの修正は次のとおりです:

// Interfacevar People = new Interface("People",["setName","getName","setAge","getAge","addHobby","getHobby","sayName","sayAge"]);var Person = function(name,age){ //implement People
  this.setName(name);
  this.setAge(age);
  this._hobbys = [];}Person.prototype = {
  //校验函数
  checkName:function(name){
    re = /\d/;
    return re.test(name);
  },
  sayName:function(){
    console.log(this._name);
  },
  sayAge:function(){
    console.log(this._age);
  },
  addHobby:function(hobbys){
    this._hobbys = this._hobbys.concat(hobbys);
  },
  getHobby:function(){
    return this._hobbys;
  },
  setName:function(name){
    if(this.checkName(name)){
      throw new Error("名字 "+name+" 不能含有数字");
    }
    this._name = name;
  },
  getName:function(){
    return this._name;
  },
  setAge:function(age){
    this._age = age || "未设置"; 
  },
  getAge:function(){
    return this._age;
  }}var person1 = new Person("Helen","20");person1.addHobby(['sing','drawing']);function record(person){
  Interface.ensureImplements(person,People);
  person.sayName();
  console.log(person.getHobby().toString());}record(person1);
ログイン後にコピー

実行結果:

Helen
sing, drawing

まず第一に、このコードではインターフェイスを使用して People インターフェイスを定義し、person がこのインターフェイスを実装していることに注意してください。コメントの内容。 (インターフェースについては、この記事「JavaScript インターフェースの使用」を参照してください)
次に、値の取得と割り当てには get メソッドと set メソッドを使用します。プログラマは set を通じてのみ値を割り当てることができ、set メソッドでは値を割り当てることができます。値を割り当てる 値が正確であることを確認するためにチェックされます。ただし、これは単なる規則です。プログラマは、person1.name = "123" を通じて値を割り当てたり、内部属性を変更したりできます。
標準化してリマインダーとして機能するために、内部属性の命名を標準化し、**_name** や **_age** など、これらの属性の前に「_」を追加します。属性を直接変更する場合は、次のように person1._name = "123" と記述する必要があります。これは明らかに意図的なアプローチであり、これは標準および注意事項として機能します。

にもかかわらず、このような規制による制限だけでは、person1._name による変更を防ぐことはできません。次の方法では、内部属性を完全にプライベート化できます。

クロージャによるカプセル化

// Interface
var People = new Interface("People",["setName","getName","setAge","getAge","addHobby","getHobby","sayName","sayAge"]);

var Person = function(name,age){ //implement People
  // 私有变量
  var _name,_age,_hobbys = [];

  this.addHobby = function(hobbys){
    _hobbys = _hobbys.concat(hobbys);
  },
  this.getHobby = function(){
    return _hobbys;
  },
  this.setName = function(name){
    if(this.checkName(name)){
      throw new Error("名字 "+name+" 不能含有数字");
    }
    _name = name;
  },
  this.getName = function(){
    return _name;
  },
  this.setAge = function(age){
    _age = age || "未设置"; 
  },
  this.getAge = function(){
    return _age;
  }

  this.setName(name);
  this.setAge(age);
}

Person.prototype = {
  checkName:function(name){
    re = /\d/;
    return re.test(name);
  },
  sayName:function(){
    console.log(this.getName());
  },
  sayAge:function(){
    console.log(this.getAge());
  }

}

var person1 = new Person("Helen","20");
person1.addHobby(['sing','drawing']);

function record(person){
  Interface.ensureImplements(person,People);
  person.sayName();
  console.log(person.getHobby().toString());
}

record(person1);
ログイン後にコピー

コンストラクタでは、属性がこれを使用しない場合、属性に外部からアクセスできず、クロージャはスコープチェーンを通じてこの属性にアクセスできます。その後、クロージャを通じて設定します。唯一のエントリポイントです。属性に値を割り当てることで、これらの属性を厳密に検証します。

ただし、多くの場合、コンストラクターでメソッドを定義する必要はありません。インスタンスが作成されるたびにメソッドのコピーが生成され、メモリのサポートが必要となるため、使用中に、使用できる場合は上記の基本的なメソッドを使用してください。プライベート属性に対する非常に厳密な検証要件がない限り、クロージャ メソッドを使用してください。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート