JSHint
、主にES6を調査することを目的として、
JSHint
にいくつかの改善を加えました(変数のスコープ検出がどのようにやり直されたかに特に誇りを持っています)。 このプロセス中に、私は驚いたいくつかのことに出くわしました-主にES6でですが、ES3に関しては今までに一度も使用したことがないものもあります。
任意のブロックからブレーク
確実に、任意のサイクルで
break
キーワードと
continue
キーワードを使用できることを知っています。これは、現代のプログラミング言語の標準機能です。 ただし、特定のループでループにラベルを付けて中断できることを誰もが知っているわけではありません。
outer: for(var i = 0; i < 4; i++) { while(true) { continue outer; } }
同じことが
break
も当てはまります。 おそらく
switch
でどのように使用されるかを見たでしょう:
switch(i) { case 1: break; }
一般的に言えば、これがCrockfordが
case
前にインデントを追加することを推奨しない理由です。break式は
case
ではなく
switch
ブロックをスローしますが、インデントされたオプションは読みやすいようです。 Switch
switch
はラベルを付けることもできます。
myswitch: switch(i) { case 1: break myswitch; }
そのようにブロックを宣言することもできます。 私はこれがC#でも利用可能であり、おそらく他の言語でも利用可能であることを知っています:
{ { console.log(" "); } }
これをすべてまとめると、ラベルを使用して任意のブロックを終了できます。
outer: { inner: { if (true) { break outer; } } console.log(" "); }
もちろん、これは
break
のみ適用されます-continueステートメントはループ内でのみ有効です。 Javascriptコードでラベルを見たことがありません-おそらく、突然複数のブロックを終了する必要がある場合、これは
return
を使用してコードを関数に書き換える機会になるためです。
ただし、単一の出口点を備えた関数を突然作成したい場合(一般的に言えば、これは私の好みではありません)-このアプローチを使用できます。 たとえば、複数の出口点がある関数:
function(a, b, c) { if (a) { if (b) { return true; } doSomething(); if (c) { return c; } } return b; }
タグを追加すると、次のようになります。
function(a, b, c) { var returnValue = b; myBlock: if (a) { if (b) { returnValue = true; break myBlock; } doSomething(); if (c) { returnValue = c; } } return returnValue; }
または、より多くのブロックを使用できます:
function(a, b, c) { var returnValue = b; if (a) { if (b) { returnValue = true; } else { doSomething(); if (c) { returnValue = c; } } } return returnValue; }
一般的に、タグ付きオプションは誰よりも好きではありませんが、おそらく慣れていないからでしょうか?
既存の変数の再構築
最初に-私が説明できないトリック。 ES3では、明らかに、割り当て時に変数を囲む括弧を追加できます。これは機能します。
var a; (a) = 1; assertTrue(a === 1);
誰かがこれを行う必要がある理由を知っている場合は、コメントに書いてください。
破壊とは、オブジェクトまたは配列から変数の値を取得するプロセスです。 ほとんどの場合、同様の例を見ることができます。
function pullOutInParams({a}, [b]) { console.log(a, b); } function pullOutInLet(obj, arr) { let {a} = obj; let [b] = arr; console.log(a, b); } pullOutInParams({a: "Hello" }, ["World"]); pullOutInLet({a: "Hello" }, ["World"]);
しかし、
let
、
var
、
const
なしでも同じことができます。 配列の場合、次のように記述します。
var a; [a] = array;
ただし、オブジェクトでは機能しません。括弧で囲む必要があります。
var a; ({a} = array);
これは、 自動セミコロン変換により識別子が計算式に変換され、副作用が発生する可能性があるため、コードの匿名ブロックに関連する曖昧な解釈とエラーの範囲が広すぎるためです。
var a = { get b() { console.log("!"); } }; with(a) { { b } }
元の例に戻ると、割り当てを括弧で囲んでいます-仮定に反して、これは破壊とは関係ありません:
var a, b, c; (a) = 1; [b] = [2]; ({c} = { c : 3 });
数値による破壊
誰もが疑うことのできない破壊の別の側面は、プロパティ名が引用符で囲まれていない文字列である必要がないことです。 これらは数字にすることができます:
var {1 : a} = { 1: true };
または引用符で囲まれた文字列:
var {"1" : a} = { "1": true };
式からプロパティの名前を計算することもできます。
var myProp = "1"; var {[myProp] : a} = { [myProp]: true };
これにより、非常にわかりにくいコードを非常に簡単に記述できます。
var a = "a"; var {[a] : [a]} = { a: [a] };
クラス宣言はブロックバウンドです
関数宣言はブロックの最上部に移動するため、宣言の前に使用できます。
func(); function func() { console.log(" "); }
ただし、変数の割り当て中に関数が宣言された場合、変数の宣言のみが発生し、変数への値の割り当ては発生しません。
func(); // func , , "func " var func = function func() { console.log(" "); };
クラスはES6仕様の最も一般的な部分の1つであり、常に関数の一種の構文糖と見なされてきました。 ただし、このコードが機能すると思われる場合は、間違いです:
new func(); class func { constructor() { console.log(" "); } }
最初の例との類似性にもかかわらず、機能しません。 これは、実際には次のコードと同等です。
new func(); let func = function func() { console.log("Fine"); }
ここでは、 一時的なデッドゾーン内の
func
にアクセスしようとしていますが、これは構文エラーです。
名前付けオプション
関数には同じ名前の2つのパラメーターを含めることはできませんが、実際には可能です!
function func(a, a) { console.log(a); } func("", ""); // ""
ただし、strictモードでは、これはそうではありません。
function func(a, a) { "use strict"; console.log(a); } func("", ""); // Chrome - SyntaxError: Strict mode function may not have duplicate parameter names
typeof
演算子は安全ではありません
わかりました、わかりました、私はこの観察を盗みましたが、それをすべて同じように繰り返すことは間違っていません。
ES6より前は、
typeof
演算子を使用すると、値が割り当てられていない場合でも識別子が宣言されているかどうかを安全に確認できることが広く知られていました。
if (typeof Symbol !== "undefined") { // Symbol } // , Symbol if (Symbol !== "undefined") { }
ただし、これは
let
または
const
変数を宣言していない場合にのみ機能します。 VSWは 、変数宣言が「内部」にあるにもかかわらず、変数の割り当て前に変数にアクセスすると構文エラーになるため、 すべてを非難することになっています。
if (typeof Symbol !== "undefined") { // Symbol } let Symbol = true; // !
配列作成
私は常に
new
キーワードを使用して配列を作成することを避けました。 主に、引数は配列またはその要素の長さのいずれかになる可能性があるためです。
new Array(1); // [undefined] new Array(1, 2); // [1, 2]
しかし、同僚が最近見たことがありませんでした。
var arr = new Array(10); for(var i = 0; i < arr.length; i++) { arr[i] = i; } console.dir(arr);
このコードは、0から9までの数字の配列を生成します。mapを使用してリファクタリングするとどうなりますか?
var arr = new Array(10); arr = arr.map(function(item, index) { return index; }); console.dir(arr);
配列は変更されていません。 どうやら、長さを受け入れるコンストラクターは配列を作成し、
length
プロパティを設定しますが、要素は作成しません。 したがって、プロパティにアクセスできますが、要素を一覧表示することはできません。 そして、要素に値を設定するとどうなりますか?
var arr = new Array(10); arr[8] = undefined; arr = arr.map(function(item, index) { return index; }); console.dir(arr);
8番目の要素に番号8が割り当てられている配列を取得しますが、他のすべての値は指定されていません。
map
関数のポリフィルコードを見ると、
in
演算子を使用してプロパティが設定されていることを確認します。 同じ動作は、配列リテラルを使用して実現できます。
var arr = []; arr[9] = undefined; // var arr = []; arr.length = 10;
その他の真珠
Mozilla開発者ブログには、コメントに
<--
記号を付けることができるという矢印関数に関する素晴らしい記事があります。 ブログの残りの記事を読んでうれしいです。