ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript クロージャ - ブロック スコープとプライベート変数

JavaScript クロージャ - ブロック スコープとプライベート変数

黄舟
黄舟オリジナル
2017-01-20 14:21:26837ブラウズ

ブロック レベル スコープ

ブロック レベル スコープとは、中括弧で囲まれたコード ブロック内のスコープを指します。 JavaScript にはブロック スコープはありません。この概念を理解するために、次の例を見てください:

for(var i = 0;i < 10; i++){
  ......
}
alert(i); //结果会输出10

上記のコードでは、for ループで変数 i を定義しました。C++ や Java などのプログラミング言語では、ループの実行が終了した後、i が定義されます。 for ループ内の変数はすぐにガベージ コレクションされます。しかし、JavaScript では、ループや何らかの判断が使用されるかどうかに関係なく、変数は常に存在します。出力結果から、for ループ終了後に出力される値が 10 であることがわかります。

ループや判定のためにグローバル環境で変数を使用する場合、その変数が関数内の変数に影響を与える可能性があるため、特別な場合を除いてグローバル変数は使用しないでください。グローバル変数は Access のスコープ チェーンの先頭にあります。が最も遅いです。

スコープをブロックする解決策は、匿名関数を使用することです。以下のコードを見てみましょう。

(function(){
  for(var i = 0; i < 10; i++){
    ......
  }
})();
 
// 直接打印i值会报错:i没有定义
alert(i);
 
// i is not defined
function fn(){
  alert(i);
}
fn();

上記のコードでは、コード ブロックを匿名関数に配置し、すぐに匿名関数を呼び出しました。匿名関数の後の括弧のペアに注目してください。これは、匿名関数の呼び出しを示しています。このスタイルの記述は多くの JavaScript プログラムで見られます。このとき、無名関数内の変数は使用後に再利用され、無名関数外からはこれらの変数にアクセスできません。

チーム開発を行う場合、同じ名前のグローバル変数を定義する必要がある場合があるため、開発中に次の習慣を身に付ける必要があります: グローバル変数のコードを匿名関数に入れ、すぐに匿名関数を呼び出す, このようにグローバル変数のコードも実行できますが、これらの変数は制御したいスコープ内で制御されます。

プライベート変数

以前にオブジェクトを定義したとき、オブジェクトのプロパティを設定するために this キーワードを使用しました。このように設定されたプロパティはパブリック プロパティと呼ばれ、オブジェクトを通じてこれらのプロパティに直接アクセスできます。

C++ や Java などのプログラミング言語では、オブジェクトのプライベート プロパティを定義するために private キーワードが使用されます。オブジェクトからプライベート プロパティに直接アクセスすることはできません。では、JavaScript でプライベート プロパティ (プライベート変数) を定義するにはどうすればよいでしょうか?実際、これは非常に簡単です。オブジェクトに対して set メソッドと get メソッドのペアを提供するだけです。たとえば、次のコード:

function Person(name){
  //此时就没有方法直接访问name这个属性,因为没有this.name
  //要访问name只能通过this.getName和this.setName来访问
  this.setName = function(value){
    name = value;
  }
  this.getName = function(){
    return name;
  }
}
 
var p = new Person("Leon");
alert(p.getName());

this.setName() メソッドを使用してオブジェクトの name 属性を設定し、this.getName メソッドを使用してオブジェクトの name 属性を取得します。このように、this.name 属性がないため、オブジェクトの name 属性に直接アクセスすることはできません。

上記の方法を使用してプライベート変数を作成する場合の問題は、各オブジェクトに多数の関数が格納され、大量のメモリを消費することです。この問題の解決策は、静的プライベート変数を使用することです。コードは次のとおりです。

var name = "";
var Person= function(value){
  name = value;
}
Person.prototype.setName = function(value){
  name = value;
}
Person.prototype.getName = function(){
  return name;
}
 
var p1 = new Person("Leon");
alert(p1.getName());
p1.setName("Ada");
alert(p1.getName());

setName() メソッドと getName() メソッドをオブジェクトのプロトタイプ チェーンに入れることにより、メソッドの複数のコピーの問題を解決できます。ただし、上記のコードにはいくつかのセキュリティ リスクがあり、これは前述したブロック レベルのスコープの問題です。同様に、このコードを匿名関数に入れることで、この問題を解決できます。

(function(){
  //name在函数结束之后就被回收,在外面是没有方法接收的
  var name = "";
  Person= function(value){
    name = value;
  }
  Person.prototype.setName = function(value){
    name = value;
  }
  Person.prototype.getName = function(){
    return name;
  }
})();
 
var p1 = new Person("Leon");
alert(p1.getName());
p1.setName("Ada");
alert(p1.getName());

Person クラスの定義を無名関数に入れて、すぐに無名関数を実行します。これにより、オブジェクトを使用してプロパティに直接アクセスできないことが保証されるだけでなく、各オブジェクトがメソッドの同じコピーを共有することも保証されます。

上記は JavaScript のクロージャブロックレベルのスコープとプライベート変数の内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。