コマンドを聞かせて
基本的な使い方
ES6は、追加の使用に似た変数、宣言してvar
、宣言された変数、唯一のlet
ブロック場所内の有効なコマンドを
{
let a = 10;
var b = 1;
}
a // a is not defined
b // 1
Varの比較サイクルのために聞かせて
// var声明
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
上記のコードは、変数がi
されvar
、世界的に有効と宣言した唯一のグローバル変数ようにi
。各サイクルでは、変数i
の値が変化するが、ループ内の配列に割り当てられているa
のfunction
実行時には、可変クロージャを通して同じを読み取りi
、最終の最終的な出力が得られ、i
値、即ち、10。
使用した場合let
、唯一の変数は、ブロックレベルのスコープで有効な宣言、最終出力は6です。
// let声明
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
};
}
a[6](); // 6
上記のコードは、変数がi
されてlet
宣言し、現在はi
そのたびサイクルは、サイクルの現在のラウンドでのみ有効ですi
実際には新しい可変で、最終的な出力があります6
。各ラウンドの可変サイクルがいる場合は、頼むかもしれi
再び、それは前のサイクルの値はサイクルの現在のラウンドの値を計算する方法を知っていることを宣言していますか?内部JavaScriptエンジンは、前のサイクルの値を覚えていますので、これは、変数がラウンドを初期化されi
、それがラウンドロビンに基づいて計算されたとき。
for
特別なループは、親スコープのループ部分であり、内側ループは、別個のサブスコープです。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上記のコードは、三回出力されるabc
内部変数の関数であることを示す、i
および外部変数がi
分離されています。
何の可変リフトはありません
var
コマンドは、変数の宣言、値の前に使用することができ、「可変リフト」現象が、発生しますundefined
。
let
このコマンドは、それ以外の場合はエラーを文法の振る舞い、それは声明の中で宣言されなければならない変数を変更するには
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
一時的なデッドゾーン
限りスコープブロックレベルがあるのでlet
、コマンド、変数は、それが外部の影響を受け、地域の「バインド」だろうと宣言しました。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
ブロックが存在する場合ES6は透明、ことlet
とconst
コマンド、このブロックを最初から変数宣言これらのコマンドは、閉じた範囲を形成します。エラーが報告される前に、文の中でこれらの変数を使用しようとする者たち。
要するに、コードブロック内のlet
変数を宣言するためのコマンドの前に、変数が使用できません。これは、文法的に「一時的なデッドゾーン」と呼ばれています
「一時的なデッドゾーン」も、ということを意味しないtypeof
、もはや百パーセント安全な操作です。
typeof x; // ReferenceError
let x;
// 如果变量没有被声明
typeof undeclared_variable // "undefined"
隠密「デッドゾーン」
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
// 解析:参数x等于参数y,但是此时参数y还没有被声明,如果是function bar(x = 2, y = x){}则不会报错,因为x已经声明,可以正常调用
// 不报错
var x = x;
// 报错
let x = x;
// ReferenceError: x is not defined
// 解析: let方式报错的原因同样是在变量x声明还没有执行完之前,取x的值
ES6一時的な規定と死んでlet
、const
文は主にあなたが予期しない動作につながる、変数宣言の前に変数を使用しないように実行時エラーを減らすために、変数を強化するためには表示されません。
文を繰り返すように許可されていません
let
文は同じ変数を繰り返し、同じスコープを許可しないでください。
// 报错
function () {
let a = 10;
var a = 1;
}
// 报错
function () {
let a = 10;
let a = 1;
}
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
ブロックレベルのスコープ
なぜ、ブロックレベルのスコープ?
非合理的なシーンの多くをもたらすES5のみグローバルスコープと関数スコープではなく、ブロックレベルのスコープ、。
最初のシナリオでは、内側層は、外側の変数の変数をカバーすることができます。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
2つ目のシナリオ、グローバル変数漏れをカウントするためのループ変数。
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
ブロックレベルのスコープES6
let
JavaScriptが実際にブロックレベルのスコープを追加しました。
ES6は、ネストされたブロックレベルの範囲を可能にします。
ブロックレベルのスコープが表示されず、実際に関数式(生命維持)の即時の実装が広く利用可能であることができるもはや必要です。
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
ブロックレベルの範囲と関数宣言
ES5は、トップレベルのスコープと関数スコープステートメントではなく、ブロックレベルの範囲のステートメントでその機能を提供します。
ブロックレベルのスコープのES6導入、明示的にブロックレベルのスコープで許可機能を宣言する。ブロックレベルの範囲内ES6規定は、動作は、関数宣言ステートメントに類似しているlet
ブロックレベルの範囲外で参照することができません。
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
上記のコードは、私たちが「私は内部のだ!」を取得、ので、ES5で実行if
宣言の機能は、f
次のコードが実際に実行され、関数の先頭に引き上げられます。
// ES5 环境
function f() { console.log('I am outside!'); }
(function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}());
ES6は、理論的には「私は外だ!」を得ます。ブロックレベルのロール内に宣言された関数が同様であるためlet
、スコープの外側には影響がありません。
あなたが本当にES6ブラウザで上記のコードを実行した場合しかし、それは、与えられていると
それはあなたがブロックレベルのスコープステートメントの処理ルールの機能を変更した場合、明らかに古いコードに重大な影響を持っていることが判明しました。これ作成の非互換性を軽減するために、内ES6 付録B、ブラウザは上記の遵守を達成することができないことを提供し、自分の持って行動する方法を。
これは、ブロックレベルのドメインの作用関数宣言することができます。
関数の宣言は似ている
var
グローバルスコープまたは関数スコープを頭に増加しますこと、。一方、関数宣言は、スコープが配置されているブロックレベルのヘッドに昇格されます。
有効ES6ための上記3つのルールのみブラウザが他の環境に準拠していない達成する、又は機能ブロックレベルのスコープを宣言することに留意されたいlet
治療。
これらの3つのルールによると、ブラウザでES6環境は、この関数は、ブロックレベルのロール内と同様の挙動宣言したvar
変数の宣言を。
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
上記のコードES6ブラウザに沿って、実際には次のコードを実行しているため、エラーになります。
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
アカウントにあまりにも異なるなどによる環境の行動を取って、ブロックレベルのスコープ関数宣言で避けるべきです。あなたが本当に必要な場合は、それはまた、式の機能ではなく、関数の宣言文として記述する必要があります。
// 函数声明语句
{
let a = 'secret';
function f() {
return a;
}
}
// 函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}
エラーが報告されていない場合ES6ブロックレベルのスコープ規則は、関数の宣言を可能にする、唯一の括弧の使用の場合に設立された、ブレース。
式を行う(理解します)
ブロックレベル・スコープ記述書、一緒にパッケージの複数の動作、戻り値がないです。
今そこにある提案値を返すことができます表現ブロックレベルの範囲になることができ、方法はブロックレベルのスコープの前に追加することでdo
、それはなるようにdo
表現。
let x = do {
let t = f();
t * t + 1;
};
constのコマンド
基本的な使い方
const
読み取り専用の定数を宣言します。文の値ならば、定数があることを意味し、変更することはできませんconst
あなたは変数を宣言したら、あなたは近い将来を初期化しなければならないの割り当てに任せることはできない、割り当てがちょうど声明ではありません、それはエラーになります。
const
スコープとlet
だけ、それが効果的に宣言されている領域でブロックレベルの役割:同じコマンド。
const
一定のコマンド文はバックの位置文で使用することができ、一時的なデッドゾーンもあり、アップグレードではありません。
自然
const
実際保証では、変数の値は変化しないわけではないが、可変ポイントのメモリアドレスが変更されてはなりません。単純なデータ型(数値、文字列、ブール値)のために、その値をメモリアドレスに格納される変数によって指し示さ、定することに等しいです。
複合データ型(主にオブジェクトおよび配列)のために、可変メモリアドレスポインタのみを保存するために指摘、const
それはデータ構造を指すように、このポインタは、固定であることを保証することができる変数ではない、完全に制御することができませんインクルード
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
上記のコードでは、定数は、foo
オブジェクトを指すアドレスに格納されています。不変だけこのアドレスは、それはないfoo
別のアドレスをポイントしますが、オブジェクト自体は、新しい属性を追加することも可能です、変数です。
オブジェクトは、あなたが使用する必要があり、凍結されているObject.freeze
方法を。
const foo = Object.freeze({});
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;
上記のコード、定数foo
凍結オブジェクトを指すが、それほど動作しない新しいプロパティを追加するだけでなく、strictモードを与えられています。
オブジェクト自体を凍結することに加えて、オブジェクトのプロパティは、凍結保存してください。以下は、完全に凍結対象の関数です。
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
変数ES6を宣言するために6つの方法
var
function
let
const
import
class
プロパティのトップレベルのオブジェクト
ブラウザ環境のトップレベルのオブジェクトは、を参照window
を参照するノード内のオブジェクトglobal
のオブジェクト。
ES5の中で、トップレベルのオブジェクトの属性とグローバル変数は等価です。
window.a = 1;
a // 1
a = 2;
window.a // 2
ES6条項
var
コマンドおよびfunction
コマンドで宣言されたグローバル変数は、まだトップレベルのオブジェクトのプロパティで、let
コマンド、const
コマンド、class
コマンドは、グローバル変数ではなく、トップレベルのオブジェクトのプロパティの一部を宣言しました
var a = 1;
// 如果在Node的REPL环境,可以写成global.a
// 或者采用通用方法,写成this.a
window.a // 1
let b = 1;
window.b // undefined
グローバルオブジェクト
ES5のトップレベルのオブジェクトは、様々な実装では、均一ではありません。
- ブラウザ内で、トップレベルのオブジェクトです
window
が、ノードおよびWebワーカーありませんwindow
。 - ブラウザとWebワーカーは、内部に、
self
また、トップレベルのオブジェクトを指すが、どのノードが存在しませんself
。 - トップレベルのオブジェクト内のノードがあります
global
が、他の環境をサポートしていません。
すべてのケースで、かろうじて2種類、トップレベルのオブジェクトを取得する方法
// 方法一
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// 方法二
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};