// ...
この形式には、単一の var 形式に固執するため、一貫性という利点があります。欠点は、コードをリファクタリングするときに、ループ全体をコピーして貼り付けるのが少し難しいことです。たとえば、ある関数から別の関数にループをコピーする場合、新しい関数に i と max を導入できることを確認する必要があります (ここで役に立たない場合は、元の関数からそれらを削除する必要がある可能性があります) ) 失う)。
JSLint がこれを実行するように要求するのは、 - 「過度の扱いやすさ」を促進するためです。 //zxx: これは、コードをさらに難しくすることが目的だと思います。
技術的には、配列に対して for-in ループを使用できます (配列は JavaScript のオブジェクトであるため) が、これはお勧めできません。配列オブジェクトがカスタム関数で拡張されている場合、ロジック エラーが発生する可能性があるためです。また、for-inでは属性リストの順序(順序)は保証されません。したがって、配列には通常の for ループを使用し、オブジェクトには for-in ループを使用するのが最善です。
非常に重要な hasOwnProperty() メソッドがあり、オブジェクトのプロパティを走査するときにプロトタイプ チェーンからプロパティをフィルターで除外できます。
この例では、オブジェクト リテラルを使用して定義された man という名前のオブジェクトがあります。 man 定義が完了した後のどこかで、 clone() と呼ばれる便利なメソッドがオブジェクト プロトタイプに追加されました。このプロトタイプ チェーンはライブです。つまり、すべてのオブジェクトが自動的に新しいメソッドにアクセスできるようになります。 man を列挙するときに clone() メソッドを回避するには、hasOwnProperty() メソッドを適用してプロトタイプのプロパティをフィルターする必要があります。フィルタリングが行われていない場合、 clone() 関数が表示されますが、これはほとんどの場合望ましくありません。
// 1.
// for-in Loop
for (var i in man) {
if (man.hasOwnProperty(i)) { // Filter
console.log(i, ":", man[i]);
}
}
/* コンソール表示結果
手: 2
脚: 2
頭: 1
*/
// 2.
/ / 裏側 例:
// hasOwnProperty() をチェックしない for-in ループ
for (var i in man) {
console.log(i, ":", man[i]); 🎜>}
/*
コンソールに結果が表示されます
hands: 2
legs: 2
heads: 1
clone: function()
*/
hasOwnProperty() を使用する別の方法は、Object.prototype のメソッドをキャンセルすることです。例:
if (Object.prototype.hasOwnProperty.call(man, i)) { // Filter
console.log(i, ":", man[i]);
}
利点は、man オブジェクトが hasOwnProperty を再定義するときに名前の競合を回避できることです。また、長いプロパティ ルックアップ オブジェクトのすべてのメソッドを回避し、ローカル変数を使用してオブジェクトを「キャッシュ」できます。
var i, hasOwn = Object.prototype。 hasOwnProperty;
for (i in man) {
if (hasOwn.call(man, i)) { // フィルター
console.log(i, ":", man[i]); 🎜>}
}
厳密に言えば、hasOwnProperty() を使用しないことは間違いではありません。タスクとコードにどの程度自信があるかによっては、ループを少しスピードアップするためにタスクをスキップできる場合があります。ただし、現在のオブジェクトの内容 (およびそのプロトタイプ チェーン) が不明な場合は、 hasOwnProperty() を追加する方が安全です。
書式変更 (JSLint によって渡されない) では、単純に中括弧が無視され、if ステートメントが同じ行に配置されます。利点は、ループ ステートメントが完全なアイデアのように読めることです (各要素には独自の属性 "X" があり、何かを行うには "X" を使用します):
// 警告: JSLint 検出に失敗しました
var i, hasOwn = Object.prototype.hasOwnProperty
; (i in man) if (hasOwn.call(man, i)) { // フィルター
console.log(i, ":", man[i]);
(非) 組み込みプロトタイプの拡張)
コンストラクターのプロトタイプ属性の拡張は、機能を追加する非常に強力な方法ですが、場合によっては強力すぎる場合があります。
組み込みのコンストラクター プロトタイプ (Object()、Array()、または Function() など) を追加する誘惑にかられますが、コードが予測不能になるため、保守性が大幅に低下します。あなたのコードを使用する他の開発者は、おそらく、あなたが追加したメソッドではなく、組み込みの JavaScript メソッドを使用して継続的に動作することを好むでしょう。
また、プロトタイプに追加されたプロパティは、hasOwnProperty 属性が使用されていないときにループ内に表示される可能性があり、混乱を引き起こす可能性があります。
したがって、組み込みプロトタイプを追加しないことが最善です。次の条件が満たされる場合にのみ例外を作成するルールを指定できます:
ECMAScript または JavaScript 実装の将来のバージョンでは、常にこの機能が組み込みメソッドとして実装されることが予想されます。たとえば、ブラウザが追いつくまで、ECMAScript 5 で説明されているメソッドを追加できます。この場合、便利なメソッドを事前に定義するだけです。
カスタム プロパティまたはメソッドが存在しないことを確認した場合、コード内の別の場所にすでに実装されているか、サポートされているブラウザの JavaScript エンジンの一部である可能性があります。
あなたは変更を明確に文書化し、チームに伝えました。
これら 3 つの条件が満たされている場合は、次の形式でプロトタイプにカスタマイズした追加を行うことができます:
if (typeof Object.protoype.myMethod !== "function") {
Object.protoype.myMethod = function () {
// 実装。 ..
};
}
switch パターン
次のような switch ステートメントを使用すると、可読性と堅牢性を高めることができます。
コードをコピー
結果 = "ゼロ";
ケース 1:
結果 = "1";
デフォルト:
>result = "unknown";
}
この簡単な例で従うスタイル規則は次のとおりです:
各ケースとスイッチを揃えます (中括弧のインデント規則を除く)
各ケースのコード インデント
各ケースはブレーク クリアで終了
貫通を避けます (ブレークは意図的に無視されます)。スルーラインが最良のアプローチであると強く確信している場合は、読者によっては間違っていると思われる可能性があるため、必ずこれを文書化してください。
デフォルトでスイッチを終了: 大文字と小文字が一致しない場合でも、常に正常な結果が得られるようにします。
暗黙的な型キャストの回避
JavaScript 変数は、比較時に暗黙的に型変換されます。そのため、false == 0 または "" == 0 は true を返します。混乱を招く暗黙的な型変換を避けるために、値と式の型を比較するときは、常に === 演算子と !== 演算子を使用してください。
コードをコピー
コードは次のとおりです:
var zero = 0;
if (zero === false) {
// ゼロは 0 で false ではないため実行されません
}
// 負の例
if (zero == false) {
// Executed...
}
== で十分だという考えもあります === は冗長です。たとえば、typeof を使用すると文字列が返されることがわかっているため、厳密な等価性を使用する理由はありません。ただし、JSLint は厳密な等価性を必要とするため、コードの見た目の一貫性が高まり、コード読み取り時のエネルギー消費が削減されます。 (「== は意図的なものですか、それとも見落としですか?」)
eval() を避ける
現在のコードで eval() を使用する場合は、「eval() は悪魔である」というマントラを思い出してください。このメソッドは任意の文字列を受け入れ、JavaScript コードとして処理します。問題のコードが事前にわかっている (実行時に決定されない) 場合、eval() を使用する理由はありません。コードが実行時に動的に生成される場合、eval を使用せずに同じ目標を達成するより良い方法があります。たとえば、角かっこ表記を使用して動的プロパティにアクセスする方が簡単で適切です。
// 否定的な例
var property = "name";
alert(eval("obj." property));
// より良い
var property = "name ";
alert(obj[property]);
eval() を使用すると、(ネットワークなどから) 実行されているコードが使用されている可能性があるため、セキュリティ上のリスクも生じます。改ざんされました。これは、Ajax リクエストからの JSON レスポンスを処理する場合によくある否定的な教訓です。このような場合、安全性と効率性を確保するには、JavaScript の組み込みメソッドを使用して JSON 応答を解析するのが最善です。ブラウザが JSON.parse() をサポートしていない場合は、JSON.org のライブラリを使用できます。
文字列を setInterval()、setTimeout()、および Function() コンストラクターに渡すことは、ほとんどの場合、eval() を使用することに似ているため、避ける必要があることを覚えておくことも重要です。舞台裏では、JavaScript はプログラムに渡す文字列を評価して実行する必要があります:
// 負の例
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)",
//より良い
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000); new Function() コンストラクトは eval() に似ているため、注意して扱う必要があります。これは強力な構成要素になる可能性がありますが、誤用されることがよくあります。どうしても eval() を使用する必要がある場合は、代わりに new Function() を使用することを検討してください。 new Function() のコード評価はローカル関数スコープで動作するため、コード内で評価される var で定義された変数は自動的にグローバル変数にならないため、潜在的な利点はわずかです。自動グローバル変数を防ぐもう 1 つの方法は、eval() 呼び出しを即時関数にラップすることです。
次の例を考えてみましょう。ここでは、un のみが名前空間をグローバル変数として汚染します。
console.log(typeof deux); // "未定義"
console.log(typeof trois); // "未定義"
var jsstring = "var un = 1; log(un );";
eval(jsstring); // ログ "1"
jsstring = "var deux = 2; console.log(deux);";
new Function(jsstring)( ); / / ログ "2"
jsstring = "var trois = 3; console.log(trois);";
(function () {
eval(jsstring);
}() ); // ログ "3"
console.log(typeof un); // 数値
console.log(typeof deux); / "unknown "
eval() と Function コンストラクトのもう 1 つの違いは、eval() がスコープ チェーンに干渉する可能性があるのに対し、Function() の方が安全であることです。 Function() をどこで実行しても、グローバル スコープのみが参照されます。したがって、局所的な変動汚染を非常によく回避できます。次の例では、 eval() は外側のスコープ内の変数にアクセスして変更できますが、Function では実行できません (using Function と new Function は同じであることに注意してください)。
コードをコピー
eval("local = 3; console.log(local)"); // ログ「3」
console.log(local); // ログ「3」
}( ));
(function () {
var local = 1;
Function("console.log(typeof local);")(); // 未定義のログを記録します
}());
parseInt() による数値変換
parseInt() を使用すると、文字列から数値を取得できます。このメソッドは省略されることが多いですが、省略すべきではありません。たとえば、文字列が「0」で始まる場合に問題が発生することがあります。たとえば、ECMAScript 3 では、フォーム フィールド部分を入力するときに、「0」で始まる文字列が 8 進数として扱われますが、これは ECMAScript で変更されました。 5.矛盾や予期しない結果を避けるために、常に基数引数を指定してください。
var month = "06",
year = "09";
month = parseInt(month, 10);
この例では、base パラメータを無視した場合parseInt (year) などの場合、戻り値は 0 になります。これは、「09」が 8 進数として扱われ (parseInt(year, 8) の実行など)、09 は 8 進数の有効な数値ではないためです。
置換方法は、文字列を次のような数値に変換することです。
"08" // 結果は 8
Number("08") // 8
これらは通常、parseInt() より高速です。 () メソッドは、名前が示すとおり、単純な解析と変換ではありません。ただし、たとえば「08 hello」と入力したい場合、parseInt() は数値を返しますが、それ以外の場合は NaN が返されます。
コーディング規約
コーディング規約を確立して従うことが重要です。これにより、コードに一貫性があり、予測可能になり、読みやすく理解しやすくなります。チームに新しく加わった開発者は、仕様を読み、他のチームメンバーが書いたコードを理解し、より早く作業を開始できます。 会議やメーリング リストでは、コーディング標準の特定の側面 (コードのインデント、タブ、スペースなど) をめぐって多くの白熱した議論が行われます。あなたが組織内での規範の採用を提案している場合は、さまざまな反対意見や強硬な意見に直面することを覚悟してください。コードを確立してしっかりと従うことは、コードの詳細にこだわるよりもはるかに重要であることを覚えておいてください。
インデント
コードは基本的にインデントなしでは読めません。唯一の問題は、インデントが一貫していないことです。仕様に従っているように見えますが、途中で混乱や驚きが生じる可能性があるからです。インデントを適切に使用することが重要です。
開発者の中には、タブのインデントを好む人もいます。これは、誰でもエディタを調整して、好みのスペース数でタブを表示できるためです。スペースを好む人もいますが、通常は 4 つですが、チームの全員が同じ基準に従っている限り、これは問題ではありません。たとえば、この本ではインデントに 4 つのスペースを使用しています。これは JSLint のデフォルトのインデントでもあります。
何をインデントする必要がありますか?ルールは単純で、中括弧の中に何を入れるかです。これは、関数本体、ループ (do、while、for、for-in)、if、switch、およびオブジェクト リテラルのオブジェクト プロパティを意味します。次のコードはインデントの使用例です。
関数アウター (a, b) {
var c = 1,
d = 2,
インナー;
if (a > b) {
インナー = function () {
return {
r: c - d
};
} else {
inner = function () {
return {
r: c d
};
};
}
return inner;
中括弧 {} (中括弧)
中括弧とも呼ばれます、以下同じ)は、オプションの場合でも常に使用する必要があります。技術的には、in または for にステートメントが 1 つしかない場合は中括弧は必要ありませんが、コードの一貫性が高まり、更新が容易になります。
ステートメントが 1 つだけある for ループがあると想像してください。解析エラーを起こさずに中括弧を無視できます。
( var i = 0; i alert(i);
しかし、後で別のコード行が追加された場合はどうなるでしょうか?
( var i = 0; i alert(i)
alert(i " は " (i % 2 ? "偶数"); 🎜>
2 番目のアラートはすでにループの外にあります。インデントに騙された可能性があります。長期的な計画の場合は、常に中括弧を使用することをお勧めします。これはコード 1 行に相当します。
// 良い例
for (var i = 0; i alert(i); >}
条件が似ている場合:
// Bad
if (true)
alert(1);
else
alert(2); {
alert(1);
} else {
alert(2);
}
開始括弧の場所)
開発者は場所について異なる設定を持っています左中括弧の - 同じ行または次の行。
alert ("それは真実です!");
}
//または
if (true)
{
alert("それは真実です!");
この例では、仁は仁を、智は智を見たが、括弧の位置が違うと行動が異なる場合もある。これはセミコロン挿入メカニズムによるものです。JavaScript は好みを選ばないので、コード行をセミコロンで終了しないことを選択した場合でも、それを補ってくれます。この動作は、たとえばオブジェクト リテラルを返し、左括弧が次の行にある場合に問題を引き起こす可能性があります:
Copy code
return
// 次のコードは実行されません
{
name : "Batman"
}
}
関数が name 属性を持つオブジェクトを返すことを期待している場合は、驚かれるでしょう。暗黙のセミコロンがあるため、関数は未定義を返します。前のコードは次と同等です:
コードをコピーします
return unknown;
// 次のコードは実行されません
{
name : "Batman"
}
}
つまり、常に中括弧を使用し、その前にステートメントを常に同じ行に置きます:
コードをコピー
name : "Batman"
};
セミコロンに関する注意: 中括弧を使用するのと同じように、セミコロンは JavaScript パーサーによって暗黙的に作成される場合でも、常に使用する必要があります。これは、より科学的で厳密なコードを促進するだけでなく、前の例で示したように、混乱している領域を解決するのにも役立ちます。
ホワイトスペース (ホワイトスペース)
ホワイトスペースの使用は、コードの読みやすさと一貫性の向上にも役立ちます。英語の文章を書くとき、カンマやピリオドの後にスペースを使います。 JavaScript では、リストのような式 (カンマに相当) と終了ステートメント (「アイデア」の完成に関連する) の後にスペースを追加することで、同じロジックに従うことができます。
スペースを使用するのに適した場所は次のとおりです。
for ループのセミコロンで区切られた部分: for (var i = 0; i for などループ 複数の変数 (i および max) が次のように初期化されます: for (var i = 0, max = 10; i
配列項目を区切るカンマの後: var a = [1, 2, 3];
オブジェクト属性のカンマと、属性名と属性値を区切るコロンの後: var o = {a: 1, b: 2}; : myFunc(a , b, c)
関数宣言の中括弧の前: function myFunc() {}
匿名関数式 function の後: var myFunc = function () {};すべての演算子とオペランドを区切るためにスペースを使用することも効果的です。つまり、-、*、=、<、>、<=、>=、===、!==、&&、||、スペースは= などの前後に必須
コードをコピー
コードは次のとおりです:if (a && b && c) { d = a % c;
a = d;
}
// 否定的な例
// スペースが欠けている、または不均等である
// コードがわかりにくくなります
var d = 0,
a = b 1;
if (a&&b&c) {
d=a % c;
注意する必要がある最後のスペースは、中括弧間のスペースです。スペースを使用するのが最善です。
関数、if-else ステートメント、ループ、オブジェクト リテラルの左中括弧 ({) の前
else または while の間の右中括弧 (})
スペースはファイルサイズが大きくなるという欠点がありますが、圧縮であればこの問題はありません。
コードの読みやすさに関して見落とされがちな側面は、垂直方向の空白の使用です。文献で段落を区切るのと同じように、空白行を使用してコード単位を区切ることができます。
命名規則
コードをより予測しやすく保守しやすくするもう 1 つの方法は、命名規則を採用することです。これは、変数と関数に同じ方法で名前を付ける必要があることを意味します。
以下は、推奨される命名規則の一部です。そのまま採用することも、好みに応じて調整することもできます。同様に、規範に従うことは、規範が何であるかよりも重要です。
コンストラクターを大文字で記述します (コンストラクターを大文字にする)
JavaScript にはクラスがありませんが、new によって呼び出されるコンストラクターがあります。 function の場合、関数名を見るだけで、これがコンストラクターであるべきか、通常の関数であるべきかがわかります。
コンストラクターに名前を付ける場合、大文字の最初の文字は暗示的な効果を持ちます。小文字で名前が付けられた関数とメソッドは、
コードをコピーしてください。 🎜> コードは次のとおりです。 function MyConstructor() {...}
function myFunction() {...}
単語の区切り )
変数名や関数名に複数の単語が含まれる場合、単語の分割については統一された標準に従うのが最善です。 「キャメルケース (キャメル) 命名法」と呼ばれる一般的な慣例があります。各単語の最初の文字を小文字にします。
コンストラクターの場合、MyConstructor() など、大文字のキャメルケースを使用できます。関数名とメソッド名には、myFunction()、calculateArea()、getFirstName() など、小文字のキャメルケースを使用できます。
変数が関数ではない場合はどうなりますか?開発者はキャメルケース表記をよく使用しますが、代わりに、first_name、favorite_bands、old_company_name のように、小文字の単語の後にアンダースコアを付けることもできます。この表記は、関数を他の識別子 (プロトタイプやオブジェクト) から視覚的に区別するのに役立ちます。
ECMAScript のプロパティとメソッドはすべて Camel 表記法を使用しますが、複数の単語を含むプロパティ名はまれです (正規表現オブジェクトの lastIndex プロパティとignoreCase プロパティ)。
その他の命名パターン
開発者は、言語機能を補ったり置き換えたりするために命名規則を使用することがあります。
たとえば、JavaScript では定数を定義する方法がないため (Number や MAX_VALUE などの組み込みの定数はいくつかありますが)、開発者はすべて大文字の規則を使用して、変数のライフ サイクル中に変更されない変数に名前を付けます。次のようなプログラム:
// 遠くからのみ見える貴重な定数
var PI = 3.14,
MAX_WIDTH = 800
コードをコピー
すべて大文字にする別の規則があります。 : グローバル変数名はすべて大文字です。グローバル変数にすべて大文字で名前を付けると、グローバル変数の数を減らすと同時に、区別しやすくなります。
仕様を使用して機能をシミュレートするもう 1 つの方法は、プライベート メンバーを使用することです。 JavaScript で真のプライベート性を実現することは可能ですが、開発者はプライベート プロパティまたはメソッドを示すためにアンダースコア接頭辞を使用する方が簡単であると考えています。次の例を考えてみましょう。
getName: function () {
return this._getFirst() ' ' this._getLast();
},
_getFirst: function () {
// ...
},
_getLast: function () {
// ...
}
};
この例では、getName() はパブリック メソッドと部分的に安定した API を表します。また、_getFirst() と _getLast() はプライベートを示します。これらは依然として通常のパブリック メソッドですが、アンダースコア接頭辞は、これらのメソッドが次のバージョンで動作することが保証されておらず、直接使用できないことを person オブジェクトのユーザーに警告するために使用されます。 noman オプションを :false に設定しない限り、JSLint はアンダースコア接頭辞を使用しないことに注意してください。
一般的な _private 仕様の一部を次に示します。
name_ や getElements_() など、プライベートを示すには末尾のアンダースコアを使用します。
_protected 属性を示すにはアンダースコア接頭辞を使用し、__private (Private) を示すには 2 つのアンダースコア接頭辞を使用します。 ) 属性
Firefox の一部の組み込み変数属性は、言語の技術的な部分に属しておらず、__proto__ と __parent__ のように、先頭の 2 つのアンダースコアと末尾の 2 つのアンダースコアで表されます。
コメントを書く
他の誰もあなたと同じようにコードに触れないとしても、コードにコメントを付ける必要があります。通常、問題を深く研究すると、コードが何に使用されているかが明確にわかりますが、1 週間後にその問題に戻ってみると、それがどのように機能するかを理解するために多くの脳細胞を費やしたはずです。
明らかに、コメントは、変数ごとに、または行ごとに、という極端な使い方はできません。ただし、通常はすべての関数、そのパラメータと戻り値、または珍しいテクニックやメソッドを文書化する必要があります。コメントは、今後コードを読む人に多くの手がかりを与える可能性があることに注意してください。読者は、コードを理解するために (あまり読みすぎなくても) コメントと関数の属性名だけを必要とします。たとえば、特定のタスクを実行するプログラムが 5 行または 6 行ある場合、その行の目的とその行が存在する理由を説明すれば、読者はこの詳細をスキップできます。コードに対するコメントの比率について厳密な規則はなく、コードの一部 (正規表現など) にはコードよりも多くのコメントが含まれる場合があります。
最も重要な習慣ですが、従うのが最も難しい習慣は、コメントを最新の状態に保つことです。古いコメントは、まったくコメントしないよりも誤解を招くためです。
著者について
Stoyan Stefanov は、Yahoo! Web 開発者、著者、寄稿者、およびオライリーの書籍の技術評論家です。彼は、カンファレンスや www.phpied.com のブログで Web 開発のトピックについて頻繁に講演しています。 Stoyan は、smush.it 画像最適化ツールの作成者でもあり、YUI の貢献者でもあり、Yahoo のパフォーマンス最適化ツール YSlow 2.0 のアーキテクトでもあります。
この記事は次から転載されています: http://www.zhangxinxu.com/wordpress/?p=1173
英語の原文: http://net.tutsplus.com/tutorials/javascript-ajax/the-ライティングの要点 - 高品質 JavaScript/
同期と結論
この記事はディレクトリ インデックスに同期されています: JavaScript を深く理解するシリーズ
詳細JavaScript の理解 一連の記事(オリジナル作成、翻訳、転載を含む) その他の種類の記事が役に立ちましたら、おじさまの書くモチベーションにつながるよう、お勧めしたり、サポートしたりしてください。