同時に、高級オブジェクト指向言語では、プライベート メンバーを含むオブジェクトの作成が最も基本的な機能の 1 つであり、プライベート メンバーにアクセスするためのプロパティとメソッドを提供することで内部の詳細が隠蔽されることもわかっています。 JS もオブジェクト指向ですが、メンバーがパブリックかプライベートかを直接示す内部メカニズムはありません。繰り返しますが、JS の言語の柔軟性を利用して、パブリック、プライベート、および特権メンバーを作成できます。情報の隠蔽が私たちが達成したい目標であり、カプセル化はこの目標を達成する方法です。例で説明しましょう。書籍データを保存し、そのデータを Web ページに表示するクラスを作成します。
1. 最も簡単なのは、オブジェクトを完全に公開することです。コンストラクターを使用して、すべてのプロパティとメソッドが外部からアクセスできるクラスを作成します。
var Book = function(isbn, title,著者) {
if(isbn == unknown) {
throw new Error("Book コンストラクターには isbn が必要です。")
}
this.isbn =
this.title; = タイトル | "";
this.author = 著者 ""
Book.prototype.display = function() {
return "書籍: " ",Title : " this.title ",Author: " this.author;
}
isbn が正しいかどうかによって表示方法が異なります。正しくない場合は取得できません画像とリンクです。これを念頭に置いて、本のタイトルと著者はオプションですが、各書籍にISBNが存在する必要があります。表面的には、isbn パラメータを指定するだけで正常に実行できるように見えます。ただし、isbn の完全性を保証することはできません。これに基づいて、書籍チェックをより堅牢にするために、isbn 検証を追加しました。
var Book = function(isbn, title,著者) {
if(!this.checkIsbn(isbn)) {
throw new Error("書籍: ISBN が無効です。")
}
this.isbn =
this; .title = タイトル || "";
this.author = 著者 || ""
book.prototype = {
checkIsbn: function(isbn) == 未定義 || isbn のタイプ != "string") return false;
isbn = isbn.replace("-", ""); 13) false を返します;
var sum == 10) {
if(!isbn.match(^d{9}))
を返します。 (var i = 0;i sum = isn.charAt(i) * (10 - i)
}
var checksum = sum % 11; (チェックサム = = 10) チェックサム = "X";
if(isbn.charAt(9) != チェックサム) return false;
} else {
if(!isbn.match(^d{12) })) false を返します;
for(var i = 0;i sum =isbn.charAt(i) * (i % 2 == 0 ? 1 : 3); 🎜>}
var checksum = sum % 10;
if(isbn.charAt(12) != checksum) return false;
}
return
},
display; : function( ) {
return "書籍: ISBN: " this.isbn ",タイトル: " this.title ",著者: " this.author;
;
ISBN の有効性を検証し、display() が正常に動作できることを確認するために checkIsbn() を追加しました。ただし、要件は変更されており、各書籍に複数のバージョンがある可能性があります。つまり、同じ書籍に複数の ISBN 番号がある可能性があり、制御のためにバージョンを選択するための別のアルゴリズムを維持する必要があります。同時に、データの整合性はチェックできますが、内部メンバーへの外部アクセスを制御できないため(isbn、タイトル、著者に値を割り当てるなど)、内部データを保護する方法はありません。私たちはこのソリューションを改善し続け、インターフェイス実装 (get アクセサー/セット メモリを提供する) を採用します。
コードをコピー
コードは次のとおりです:
var Publication = new Interface("Publication", ["getIsbn", "setIsbn", "checkIsbn", "getTitle", "setTitle", "getAuthor", "setAuthor", "display"]) ;
var Book = function(isbn, title, author) {
// Publication インターフェイスを実装します
this.setIsbn(isbn);
this.setTitle(タイトル);
this.setAuthor(著者);
}
Book.prototype = {
getIsbn: function() {
return this.isbn;
},
setIsbn: function(isbn) {
if(!this.checkIsbn(isbn)) {
throw new Error("書籍: 無効な ISBN。");
}
this.isbn = isb;
},
checkIsbn: function(isbn) {
if(isbn == 未定義 || typeof isbn != "string") return false;
isbn = isbn.replace("-", "");
if(isbn.length != 10 &&isbn.length != 13) は false を返します。
変数合計 = 0;
if(isbn.length == 10) {
if(!isbn.match(^d{9})) false を返します。
for(var i = 0;i sum =isbn.charAt(i) * (10 - i);
}
var checksum = sum % 11;
if(チェックサム == 10) チェックサム = "X";
if(isbn.charAt(9) != チェックサム) false を返します。
} else {
if(!isbn.match(^d{12})) return false;
for(var i = 0;i sum = isbn.charAt(i) * (i % 2 == 0 ? 1 : 3);
}
var checksum = sum % 10;
if(isbn.charAt(12) != チェックサム) false を返します。
}
true を返します。
},
getTitle: function() {
return this.title;
},
setTitle: function(title) {
this.title = title || "";
},
getAuthor: function() {
return this.author;
},
setAuthor: function(author) {
this.author = 著者 || "";
},
display: function() {
return "書籍: ISBN: " this.isbn ",タイトル: " this.title ",著者: " this.author;
}
};
この方法は、同様のテストを 2 回実行する必要がなく、完全な完全なエクスポーズ オブジェクト スキームと同様に、アーキテクチャの内部でも実行されます。この方法は、メモリを設定することによって設定することができるが、公開されており、値を直接評価することもできる。
2. 唯一の欠点は、内部データを保護できず、余分なコードが追加されることです。 命名規則の私的方法を使用する。つまり、下位ラインを使用して私が所有者であることを認識し、私が所有者に評価値を適用することを回避し、本質的には完全な暴露対象を回避する。
var Publication = new Interface("Publication", ["getIsbn", "setIsbn", "getTitle" 、「setTitle」、「getAuthor」、「setAuthor」、「display」]);
var Book = function(isbn, title, author) {
// Publication インターフェイスを実装します
this.setIsbn(isbn);
this.setTitle(タイトル);
this.setAuthor(著者);
}
Book.prototype = {
getIsbn: function() {
return this._isbn;
},
setIsbn: function(isbn) {
if(!this._checkIsbn(isbn)) {
throw new Error("書籍: 無効な ISBN。");
}
this._isbn = isbn;
},
_checkIsbn: function(isbn) {
if(isbn == 未定義 || typeof isbn != "string") return false;
isbn = isbn.replace("-", "");
if(isbn.length != 10 &&isbn.length != 13) は false を返します。
変数合計 = 0;
if(isbn.length == 10) {
if(!isbn.match(^d{9})) return false;
for(var i = 0;i sum =isbn.charAt(i) * (10 - i);
}
var checksum = sum % 11;
if(チェックサム == 10) チェックサム = "X";
if(isbn.charAt(9) != チェックサム) false を返します。
} else {
if(!isbn.match(^d{12})) return false;
for(var i = 0;i sum = isbn.charAt(i) * (i % 2 == 0 ? 1 : 3);
}
var checksum = sum % 10;
if(isbn.charAt(12) != チェックサム) false を返します。
}
true を返します。
},
getTitle: function() {
return this._title;
},
setTitle: function(title) {
this._title = title || "";
},
getAuthor: function() {
return this._author;
},
setAuthor: function(author) {
this._author = 著者 || "";
},
display: function() {
return "書籍: ISBN: " this.getIsbn() ",タイトル: " this.getTitle() ",著者: " this.getAuthor();
}
};
注: 「_」でプライベート メンバーとしてマークされるisbn、title、author属性に加えて、checkIsbn() もプライベート メソッドとしてマークされます。
3. クロージャを通じてメンバーを本当に私物化する。クロージャの概念におけるスコープとネストされた関数に詳しくない場合は、ここでは詳しく説明しませんが、記事「オブジェクト指向 Javascript の 1 つ (初めての Javascript 入門)」を参照してください。
var Publication = new Interface("Publication" , [" getIsbn", "setIsbn", "getTitle", "setTitle", "getAuthor", "setAuthor", "display"]);
var Book = function(newIsbn, newTitle, newAuthor) {
// プライベート属性
var isbn, title, author;
// プライベート メソッド
function checkIsbn(isbn) {
if(isbn == unknown || typeof isbn != "string") return false;
isbn = isbn.replace("-", "");
if(isbn.length != 10 &&isbn.length != 13) return false; 🎜>if (isbn.length == 10) {
if(!isbn.match(^d{9})) return false;
for(var i = 0;i sum = isn.charAt(i) * (10 - i);
}
var checksum = sum % 11;
if(checksum == 10) checksum = "X"; >if(isbn.charAt(9) != チェックサム) return false;
} else {
if(!isbn.match(^d{12})) return false; 0;i sum = isn.charAt(i) * (i % 2 == 0 ? 1 : 3);
var checksum = sum % 10; 🎜>if (isbn.charAt(12) != checksum) return false;
}
return true;
}
// 特権メソッド
this.getIsbn = function() {
return
};
this.setIsbn = function(newIsbn) {
if(!checkIsbn(newIsbn)) {
throw new Error("書籍: 無効な ISBN。");
}
isbn = newIsbn;
}
this.getTitle = function() {
タイトルを返す;
},
this.setTitle = function(newTitle) {
title = newTitle || "";
},
this.getAuthor: function() {
著者を返す;
},
this.setAuthor: function(newAuthor) {
author = newAuthor || "";
}
// 出版物インターフェース
this.setTitle(newTitle); );
}
// public メソッド
Book.prototype = {
display: function() {
return "書籍: ISBN: " this.getIsbn() ",Title: " this.getTitle () ",Author: " this.getAuthor();
}
};
このソリューションと前のソリューションの違いは何ですか?まず、コンストラクター内で var を使用して 3 つのプライベート メンバーを宣言し、コンストラクター内でのみ有効なプライベート メソッド checkIsbn() も宣言します。 this キーワードを使用して特権メソッドを宣言します。つまり、コンストラクター内で宣言されますが、プライベート メンバーにアクセスできます。プライベート メンバーにアクセスする必要のないメソッドはすべて Book.prototype で宣言されます (display など)。つまり、プライベート メンバーにアクセスする必要があるメソッドを特権メソッドとして宣言することが、この問題を解決する鍵となります。ただし、このアクセスにはいくつかの欠点もあります。たとえば、インスタンスごとに特権メソッドのコピーを作成する必要があり、必然的により多くのメモリが必要になります。私たちは、直面している問題を解決するために静的メンバーの最適化と使用を続けています。ちなみに、静的メンバーはクラスにのみ属し、すべてのオブジェクトは 1 つのコピーのみを共有します (「オブジェクト指向 Javascript 2 (インターフェイスの実装)」で説明されています。「Interface.ensureImplements メソッド」を参照)。一方、インスタンス メソッドは Word オブジェクト用です。
コードをコピー
コードは次のとおりです:
var Publication = new Interface("Publication", ["getIsbn", "setIsbn", "getTitle", "setTitle", "getAuthor", "setAuthor", "display"]);
var Book = (function() {
// プライベート静的属性
var numsOfBooks = 0;
// プライベート静的メソッド
function checkIsbn(isbn) {
if(isbn == 未定義 || isbn のタイプ != "string") return false;
isbn = isbn.replace("-", ""); 13) false を返します;
var sum == 10) {
if(!isbn.match(^d{9}))
を返します。 (var i = 0;i sum = isn.charAt(i) * (10 - i)
}
var checksum = sum % 11; (チェックサム == 10) チェックサム = "X";
if(isbn.charAt(9) != チェックサム) return false;
} else {
if(!isbn.match(^d{12) })) false を返します;
for(var i = 0;i sum =isbn.charAt(i) * (i % 2 == 0 ? 1 : 3); 🎜>}
var checksum = sum % 10;
if(isbn.charAt(12) != checksum) return false;
}
return
}
// return コンストラクター
return function(newIsbn, newTitle, newAuthor) {
// プライベート属性
var isbn, title, author;
// 特権メソッド
this.getIsbn = function() {
isbn を返す;
};
this.setIsbn = function(newIsbn) {
if(!Book.checkIsbn(newIsbn)) {
throw new Error("書籍: 無効な ISBN。");
}
isbn = newIsbn;
}
this.getTitle = function() {
タイトルを返す;
},
this.setTitle = function(newTitle) {
title = newTitle || "";
},
this.getAuthor = function() {
著者を返す;
},
this.setAuthor = function(newAuthor) {
author = newAuthor || "";
}
Book.numsOfBooks ;
if(Book.numsOfBooks > 50) {
throw new Error("Book: Book のインスタンスは最大 50 個作成できます。");
}
// Publication インターフェース
this.setIsbn(newIsbn); を実装します。
this.setTitle(newTitle);
this.setAuthor(newAuthor);
};
})();
// public static メソッド
Book.convertToTitle = function(title) {
return title.toUpperCase();
}
// public メソッド
Book.prototype = {
display: function() {
return "Book: ISBN: " this.getIsbn() ",Title: " this. getTitle() ",Author: " this.getAuthor();
}
};
この方法は上記と同様に、var と this を使用して静的メソッドを構築することと、checkIsbn を私的静的メソッドとして指定する点が異なります。必要に応じて、私たちがすべてのオブジェクトを公開する 1 つの関数をサブ本にするという解決策を考えています。ここで私たちは 1 つの問題を検討し、<>の最大印刷量が 500 であるなど、さまざまな制限を設ける必要があると考えています。 <<.NET>> 最大印刷量は 1000 であり、つまり、最大印刷量の定期的な量が必要です。
暗号化
暗号化は次のように実行できます。
var Publication = new Interface("Publication", ["getIsbn", "setIsbn", "getTitle", "setTitle", "getAuthor", "setAuthor", "display"]);
var Book = (function() {
// プライベート静的属性
var numsOfBooks = 0;
// プライベート静的定数
var Constants = {
"MAX_JAVASCRIPT_NUMS": 500 ,
"MAX_NET_NUMS": 1000
};
// プライベート静的特権メソッド
this.getMaxNums(name) {
return Constants[name.ToUpperCase()];
// private static メソッド
function checkIsbn(isbn) {
if(isbn == unknown || typeof isbn != "string") return false;
isbn = isbn.replace("- ", "");
if(isbn.length != 10 &&isbn.length != 13) return false;
var sum = 0;
if(isbn.length == 10) {
if(!isbn.match(^d{9})) return false;
for(var i = 0;i sum = isbn.charAt(i) * ( 10 - i);
var checksum = sum % 11;
if(checksum == 10) checksum = "X"; return false;
} else {
if(!isbn.match(^d{12})) return false;
for(var i = 0;i sum = isbn.charAt(i) * (i % 2 == 0 ? 1 : 3);
}
var checksum = sum % 10>if(isbn.charAt(12) != checksum ) false を返します。
}
true を返します。
}
// return コンストラクター
return function(newIsbn, newTitle, newAuthor) {
// プライベート属性
var isbn, title, author;
// 特権メソッド
this.getIsbn = function() {
return isbn;
};
this.setIsbn = function(newIsbn) {
if(!Book.checkIsbn(newIsbn)) {
throw new Error("書籍: 無効な ISBN。");
}
isbn = newIsbn;
}
this.getTitle = function() {
タイトルを返す;
},
this.setTitle = function(newTitle) {
title = newTitle || "";
},
this.getAuthor = function() {
著者を返す;
},
this.setAuthor = function(newAuthor) {
author = newAuthor || "";
}
Book.numsOfBooks ;
if(Book.numsOfBooks > 50) {
throw new Error("Book: Book のインスタンスは最大 50 個作成できます。");
}
// Publication インターフェース
this.setIsbn(newIsbn); を実装します。
this.setTitle(newTitle);
this.setAuthor(newAuthor);
};
})();
// public static メソッド
Book.convertToTitle = function(title) {
return title.toUpperCase();
}
// public メソッド
Book.prototype = {
display: function() {
return "Book: ISBN: " this.getIsbn() ",Title: " this. getTitle()
",Author: " this.getAuthor() "、最大値: ";
},
showMaxNums: function() {
return Book.getMaxNums("MAX_JAVASCRIPT_NUMS");
}
};
最も完璧な場合は、パッケージ化されたプログラムが管理者にとって必要なだけであり、どのように実行されるかは根本的に考慮されていません。必然的に、パッケージングされたコンテンツが大きくなり、ターゲットのやり取りが発生すると、有効領域やパケットなどの概念が十分に理解されていないため、要求がこれほど大きくなる場合があります。ソース コード (ここでは必ずしもインターフェイスの変更を意味するわけではありません) は、送信されたソース コードが劣化していない限り、新しく追加される可能性があるため、推奨されません。扩展。