let

  • リビジョンの URL スラッグ: Web/JavaScript/Reference/Statements/let
  • リビジョンのタイトル: let
  • リビジョンの ID: 420247
  • 作成日:
  • 作成者: ethertank
  • 現行リビジョン はい
  • コメント 翻訳を進めたMoved From JavaScript/Reference/Statements/let to Web/JavaScript/Reference/Statements/let

このリビジョンの内容

{{translationInProgress}}{{js_minversion_header("1.7")}}

概要

局所変数を宣言します。任意で値を代入して初期化できます。

構文

let 宣言:

let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];

let 式:

let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;

let 文:

let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) statement;

引数

引数 説明
var1, var2, …, varN 変数の名前。任意の有効な識別子を指定できます。
value1, value2, …, valueN 変数の初期値。任意の有効な式を指定できます。
expression 任意の有効な
statement 任意の有効な

説明

let を使用することで、変数のスコープをそれが使用されたブロック、文または式に限定することができます。

これは var (ブロックスコープに関係なく、グローバルな、もしくはある関数全体でのローカルな変数を定義する)とは異なります。

ブロックスコープ

let で宣言された変数はそれを取り囲んでいるブロックの先頭へ引き上げられます。

同じブロック内で同じ変数を再宣言すると TypeError が発生します。

if (x) {
  let foo;
  let foo; // TypeError が発生
}

しかし、関数の本体ではこの制限はありません!

function do_something() {
  let foo;
  let foo; // これは正常に動作します
}
警告: ECMAScript 6 草案(2012年4月時点)ではこの動作を不正なものとしています。つまり、未来のバージョンの JavaScript では首尾一貫して TypeError が発生するでしょう。もしあなたがこれをしているとしたら、その悪習は避けるべきです。

switch 文を使用する際、そこには1つしかブロックが無いため、例外を発生させてしまうかもしれません。

switch (x) {
  case 0:
    let foo;
    break;
    
  case 1:
    let foo; // 再宣言による TypeError
    break;
}

let 式 で宣言された変数は、その式の中でのみ有効です。

var a = 5;
let(a = 6) alert(a); // 6
alert(a); // 5

ブロック内で使用されると、 let  で宣言された変数はそのブロック内でのみ有効となります。 var で宣言された変数が宣言された関数内で有効となることとの違いに注意して下さい。

var a = 5;
var b = 10;

if (a === 5) {
  let a = 4; // 変数aはifブロック内で有効
  var b = 1; // 変数bはfunction内で有効

  console.log(a);  // 4
  console.log(b);  // 1
} 

console.log(a); // 5
console.log(b); // 1

ループにおいて、var で定義されたグローバル変数を使う代わりに、let キーワードによってループ内でのローカル変数を使用することができます。

for (let i = 0; i<10; i++) {
  alert(i); // 1, 2, 3, 4 ... 9
}

alert(i); // i は未定義

コンストラクタを仕様する際に let 文を用いることで、クロージャを使用せずにprivateなインターフェースを作成することができます。

/*\
|*|
|*|  :: A public and reusable API for constructors ... ::
|*|
\*/
 
let (
  switchScope = function (oOwner, fConstructor) {
    return oOwner && oOwner.constructor === fConstructor ? oOwner : this;
  }
) {
  function buildIndoors (fConstructor) {
    const oPrivate = new fConstructor(this);
    this.getScope = oPrivate.getScope = switchScope.bind(this, oPrivate);
    return oPrivate;
  }
}
 
/*\
|*|
|*|  :: Use of the *let* statement in order to create a private interface without closures... ::
|*|
\*/
 
let (
 
  /* "Secrets" is the constructor of the private interface */
 
  Secrets = function Secrets (oPublic /* (the public interface) */) {
    /* setting a private property... */
    this.password = Math.floor(Math.random() * 1e16).toString(36);
    /* you can also store the public interface into a private property... */
    /* this.publicInterface = oPublic; */
    alert("I\'m getting a public property from a private constructor...: somePublicProperty: " + oPublic.somePublicProperty);
  }
 
) {
 
  /* "User" is the constructor of the public interface */
 
  function User (sNick) {
    /* setting a public property... */
    this.somePublicProperty = "Hello World!";
    const oPrivate = this.createScope(Secrets); /* (the private interface) */
    /* setting a public property... */
    this.user = sNick;
    alert("I\'m getting a private property from a public constructor...: password: " + oPrivate.password);
  }
 
  User.prototype.somePublicMethod = function () {
    const oPrivate = this.getScope(Secrets); /* (the private interface) */
    alert("I\'m getting a public property from a public method...: user: " + this.user);
    alert("I\'m getting a private property from a public method...: password: " + oPrivate.password);
    oPrivate.somePrivateMethod();
  };
 
  Secrets.prototype.somePrivateMethod = function () {
    const oPublic = this.getScope(); /* (the public interface) */
    alert("I\'m getting a public property from a private method...: user: " + oPublic.user);
    alert("I\'m getting a private property from a private method...: password: " + this.password);
  };
 
  /* ...creating a mutual access... */
 
  User.prototype.createScope = buildIndoors;
}
 
/* out of the *let* statement you have not access to the private interface! */
 
const johnSmith = new User("John Smith");
johnSmith.somePublicMethod();

関連情報

このリビジョンのソースコード

<div>
  {{translationInProgress}}{{js_minversion_header("1.7")}}</div>
<h2 id="Summary" name="Summary">概要</h2>
<p>局所変数を宣言します。任意で値を代入して初期化できます。</p>
<h2 id="Syntax" name="Syntax">構文</h2>
<p><code>let</code> 宣言:</p>
<pre class="syntaxbox">
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
</pre>
<p><code>let</code> 式:</p>
<pre class="syntaxbox">
let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;
</pre>
<p><code>let</code> 文:</p>
<pre class="syntaxbox">
let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) statement;
</pre>
<h3 id="Parameters" name="Parameters">引数</h3>
<table class="standard-table">
  <thead>
    <tr>
      <th scope="col">引数</th>
      <th scope="col">説明</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>var1</code>, <code>var2</code>, …, <code>varN</code></td>
      <td>変数の名前。任意の有効な識別子を指定できます。</td>
    </tr>
    <tr>
      <td><code>value1</code>, <code>value2</code>, …, <code>valueN</code></td>
      <td>変数の初期値。任意の有効な式を指定できます。</td>
    </tr>
    <tr>
      <td><code>expression</code></td>
      <td>任意の有効な <a href="/ja/docs/JavaScript/Guide/Expressions_and_Operators#Expressions" title="JavaScript/Guide/Expressions and Operators#Expressions">式</a></td>
    </tr>
    <tr>
      <td><code>statement</code></td>
      <td>任意の有効な <a href="/ja/docs/JavaScript/Reference/Statements" title="JavaScript/Reference/Statements">文</a></td>
    </tr>
  </tbody>
</table>
<h2 id="Description" name="Description">説明</h2>
<p><code>let</code>&nbsp;を使用することで、変数のスコープをそれが使用されたブロック、文または式に限定することができます。</p>
<p>これは <code>var</code> (ブロックスコープに関係なく、グローバルな、もしくはある関数全体でのローカルな変数を定義する)とは異なります。</p>
<h2 id="Block_scoping" name="Block_scoping">ブロックスコープ</h2>
<p><code>let</code> で宣言された変数はそれを取り囲んでいるブロックの先頭へ引き上げられます。</p>
<p>同じブロック内で同じ変数を再宣言すると <code><a href="/ja/docs/JavaScript/Reference/Global_Objects/TypeError" title="TypeError">TypeError</a></code> が発生します。</p>
<pre class="brush: js">
if (x) {
  let foo;
  let foo; // TypeError が発生
}</pre>
<p>しかし、関数の本体ではこの制限はありません!</p>
<pre class="brush: js">
function do_something() {
  let foo;
  let foo; // これは正常に動作します
}</pre>
<div class="warning">
  <strong>警告:</strong> ECMAScript 6 草案(2012年4月時点)ではこの動作を不正なものとしています。つまり、未来のバージョンの JavaScript では首尾一貫して <code><a href="/ja/docs/JavaScript/Reference/Global_Objects/TypeError" title="TypeError">TypeError</a></code>&nbsp;が発生するでしょう。もしあなたがこれをしているとしたら、その悪習は避けるべきです。</div>
<p><a href="/ja/docs/JavaScript/Reference/Statements/switch" title="switch"><code>switch</code></a>&nbsp;文を使用する際、そこには1つしかブロックが無いため、例外を発生させてしまうかもしれません。</p>
<pre class="brush: js">
switch (x) {
  case 0:
    let foo;
    break;
    
  case 1:
    let foo; // 再宣言による TypeError
    break;
}</pre>
<h2 id="Examples" name="Examples">例</h2>
<p><em>let 式</em> で宣言された変数は、その式の中でのみ有効です。</p>
<pre class="brush: js">
var a = 5;
let(a = 6) alert(a); // 6
alert(a); // 5</pre>
<p>ブロック内で使用されると、<em> let &nbsp;</em>で宣言された変数はそのブロック内でのみ有効となります。 <em>var</em> で宣言された変数が宣言された関数内で有効となることとの違いに注意して下さい。</p>
<pre class="brush: js">
var a = 5;
var b = 10;

if (a === 5) {
  let a = 4; // 変数aはifブロック内で有効
  var b = 1; // 変数bはfunction内で有効

  console.log(a);  // 4
  console.log(b);  // 1
} 

console.log(a); // 5
console.log(b); // 1</pre>
<p>ループにおいて、<em>var </em>で定義されたグローバル変数を使う代わりに、<em>let</em>&nbsp;キーワードによってループ内でのローカル変数を使用することができます。</p>
<pre class="brush: js">
for (let i = 0; i&lt;10; i++) {
  alert(i); // 1, 2, 3, 4 ... 9
}

alert(i); // i は未定義</pre>
<p>コンストラクタを仕様する際に let 文を用いることで、クロージャを使用せずにprivateなインターフェースを作成することができます。</p>
<pre class="brush: js">
/*\
|*|
|*|  :: A public and reusable API for constructors ... ::
|*|
\*/
 
let (
  switchScope = function (oOwner, fConstructor) {
    return oOwner &amp;&amp; oOwner.constructor === fConstructor ? oOwner : this;
  }
) {
  function buildIndoors (fConstructor) {
    const oPrivate = new fConstructor(this);
    this.getScope = oPrivate.getScope = switchScope.bind(this, oPrivate);
    return oPrivate;
  }
}
 
/*\
|*|
|*|  :: Use of the *let* statement in order to create a private interface without closures... ::
|*|
\*/
 
let (
 
  /* "Secrets" is the constructor of the private interface */
 
  Secrets = function Secrets (oPublic /* (the public interface) */) {
    /* setting a private property... */
    this.password = Math.floor(Math.random() * 1e16).toString(36);
    /* you can also store the public interface into a private property... */
    /* this.publicInterface = oPublic; */
    alert("I\'m getting a public property from a private constructor...: somePublicProperty: " + oPublic.somePublicProperty);
  }
 
) {
 
  /* "User" is the constructor of the public interface */
 
  function User (sNick) {
    /* setting a public property... */
    this.somePublicProperty = "Hello World!";
    const oPrivate = this.createScope(Secrets); /* (the private interface) */
    /* setting a public property... */
    this.user = sNick;
    alert("I\'m getting a private property from a public constructor...: password: " + oPrivate.password);
  }
 
  User.prototype.somePublicMethod = function () {
    const oPrivate = this.getScope(Secrets); /* (the private interface) */
    alert("I\'m getting a public property from a public method...: user: " + this.user);
    alert("I\'m getting a private property from a public method...: password: " + oPrivate.password);
    oPrivate.somePrivateMethod();
  };
 
  Secrets.prototype.somePrivateMethod = function () {
    const oPublic = this.getScope(); /* (the public interface) */
    alert("I\'m getting a public property from a private method...: user: " + oPublic.user);
    alert("I\'m getting a private property from a private method...: password: " + this.password);
  };
 
  /* ...creating a mutual access... */
 
  User.prototype.createScope = buildIndoors;
}
 
/* out of the *let* statement you have not access to the private interface! */
 
const johnSmith = new User("John Smith");
johnSmith.somePublicMethod();</pre>
<h2 id="See_also" name="See_also">関連情報</h2>
<ul>
  <li><a href="/ja/docs/JavaScript/Reference/Statements/var" title="JavaScript/Reference/Statements/var"><code>var</code></a></li>
  <li><a href="/ja/docs/JavaScript/Reference/Statements/const" title="JavaScript/Reference/Statements/const"><code>const</code></a></li>
  <li><a href="/ja/docs/JavaScript/New_in_JavaScript/1.7#Block_scope_with_let" title="JavaScript/New in JavaScript/1.7#Block scope with let">JavaScript 1.7 の新機能</a></li>
</ul>
Revert to this revision