この記事は公開または最後に更新されてから2253日が経過しています。情報が古くなっている可能性があるのでご注意下さい。

Javascript Coding Standard コーディング基準

ちょっと思い立って、WordPress のコーディング規約なるものに目を通して見ました。
PHPに関してはcodex に訳したページがあって助かったのですが、このjavascript に関しては無かったので自分で訳すしかありません。
ぺージにしておけば、忘れてしまった時に後で何度でも見直せます。

WordPressのオリジナルページへのリンクは、『 WordPress Javascript Coding Standard 』
日本語訳は翻訳サイトを利用しつつ、私が訳したものなのでかなり怪しげではあると思います。所々、訳せなくて意味不明の部分が存在しますので、あしからず。以下、緑文字が原文、青文字が日本語訳。
その冒頭には、

All code in any code-base should look like a single person typed it, no matter how many people contributed. – Principles of Writing Consistent, Idiomatic JavaScript

どんなコードベースであれ全てのコードは、たとえどんなにたくさんの人が貢献したものであったにしても、一人が書いたように見えるものであるべきである。
そして、

The WordPress JavaScript Coding Standards are adapted from the jQuery JavaScript Style Guide. Our standard differs from the jQuery guidelines in the following ways:

・WordPress uses single quotation marks for string declarations.
・Case statements are indented within switch blocks.
・Function contents are consistently indented, including full-file closure wrappers.
・Some whitespace rules differ, for consistency with the WordPress PHP coding standards.
・jQuery’s 100-character hard line limit is encouraged, but not strictly enforced.

Many of the examples below have been adapted directly from the jQuery style guide; these differences have all been integrated into the examples on this page. Any of the below standards and examples should be considered best practice for WordPress code, unless explicitly noted as anti-patterns.

WordPressのJavaScriptにおけるコーディング規約は、jQuery JavaScript Style Guide から適合されます。我々の規約は、以下の方法でjQueryのガイドラインとは異なります。

  • WordPressは、文字列の定義には単一引用符を使用しています。
  • case文はswitchブロック内でインデントされています。
  • functionの内容部分は全てファイルを閉じるための最後部のラッパーを含めてインデントされています。
  • WordPressのPHPコーディング規約との整合性のために、いくつかのスペースのルールは異なっています。
  • jQueryの強度な1行100文字制限を奨励していますが、厳密には施行されていません。

以下の例の多くは、jQueryのスタイルガイドから直接適応されています。これらの違いは、すべてこのページの例に統合されました。明白にアンチパターンとして注記されない限り、以下の規約および実施例のどれもが、WordPressのコードのための最善なる慣習として考慮されるべきです。
とあるので、このページにあるのは Idiomatic JavaScript と jQuery style guideを照らし合わせつつ、そしてWordPress standard を主にしてまとめたものです。

≪ Spacing ≫

これらのルールは、進歩した開発者の読みやすさのために大まかなスペースの使用を奨励しています。minification(ファイル圧縮化)は、ブラウザが読み込んで処理するために最適化されたファイルを作成します。

  • インデントはタブを使用する。
  • 行の終わり、また空行にはスペースはあってはならない。
  • 行は80文字を超えてはならない、そしてタブを4つのスペースとしてカウントして100文字を超えてはなりません。これは緩い規則ですが、一般に長い行は読みづらく混乱させるコードであることを示しています。
  • if/else/for/while/try ブロックは常にbrace{}を使用し、複数の行にかかるようにします。
  • 単項特殊文字演算子(たとえば、!、++、--)は、その演算子に接してスペースがあってはいけません。
  • いずれの,; はスペースが前にあってはいけません。
  • いずれの;は、文の終了記号として使用するには、行の末尾になければいけません。
  • オブジェクト定義におけるプロパティ名の後の:は、スペースが前にあってはいけません。
  • 三項演算子における?:は、その両側にスペースを使用します。
  • 空のカッコ内にはスペースは使用しない。(例えば {}, [], fn())。
  • 各ファイルの末尾には新しい空行が必要。
  • いずれの否定演算子!においては、それに続くスペースを使用する。
  • ファイル全体がクローじゃで包含されている場合でも、すべての関数の本体は一つのタブでインデントされています。
  • スペースはドキュメントブロック内または行内のコードを整列することに使用できるが、先頭において使用されるべきはタブだけです。

*WordPressのJavaScriptの規約は、jQueryのスタイルガイドよりもわずかに広い空白のルールを選択しています。これらの違いは、WordPressのコードベースにおけるPHPとJavaScriptのファイルの間の一貫性を保つためです。

スペースは簡単に行の末尾にたまってしまいます。 -これを避けるには、 JSHintでは連なったスペースはエラーとしてキャッチされます。蓄積されたスペースをキャッチするもう1つの方法は、テキストエディタ内でスペースを見えるようにすることです。

Object オブジェクト

オブジェクトの宣言は、それが短い場合は(ライン長のガイドラインを思い出してください)1行で行うことができます。1行に収まらない場合には、1行につき1つのプロパティだけをあてます。プロパティ名は予約された言葉、または特殊文字が含まれている場合に引用符で囲む必要があります。

// より良い
var map = {
	ready: 9,
	when: 4,
	'you are': 15
};

// 小さいオブジェクトであれば無難
var map = { ready: 9, when: 4, 'you are': 15 };

// 悪い例
var map = { ready: 9,
	when: 4, 'you are': 15 };
JavaScript
CopyExpand
Arrays and Function Calls 配列と関数呼び出し

常に要素と引数の周りに付加したスペースが含まれています。

array = [ a, b ];

foo( arg );

foo( 'string', object );

foo( options, object[ property ] );

foo( node, 'property', 2 );
JavaScript
CopyExpand

例外

// PHP規約との整合性のために
// 配列の表記においてキーの値に文字列または整数を使用する場合は両側にスペースは付加しない
prop = object['default'];
firstArrayElement = arr[0];

// 単独の引数としてのコールバック関数、オブジェクト、配列を持つ場合
// 引数の両側にはスペースは付加しない
foo(function() {
	// 文
});

foo({
	a: 'alpha',
	b: 'beta'
});

foo([
	'alpha',
	'beta'
]);

// 一つ目の引数としてのコールバック関数、オブジェクト、配列を持つ場合
// 一つ目の引数の前にはスペースは付加しない
foo(function() {
	// 文
}, options );

// 最後の引数としてのコールバック関数、オブジェクト、配列を持つ場合
// 最後の引数の後にはスペースは付加しない
foo( data, function() {
	// 文
});
JavaScript
CopyExpand
Example of Good Spacing スペーシングの良い例
var i;

if ( condition ) {
	doSomething( 'with a string' );
} else if ( otherCondition ) {
	otherThing({
		key: value,
		otherKey: otherValue
	});
} else {
	somethingElse( true );
}

// jQueryとは違いますが、WordPress では論理演算子NOT! の後にスペースを付加することを選択します。
// これもまた我々のPHP規約と一貫性を保つためです。
while ( ! condition ) {
	iterating++;
}

for ( i = 0; i < 100; i++ ) {
	object[ array[ i ] ] = someFn( i );
	$( '.container' ).val( array[ i ] );
}

try {
	// 式
} catch ( e ) {
	// 式
}
JavaScript
CopyExpand
Indentation and Line Breaks インデントと改行

インデントや改行は、複雑な文に読みやすさを追加します。
インデントにはタブが使用されるべきです。ファイル全体がクロージャ(すなわち、すぐに呼び出される関数)に含まれている場合でも、その関数の内容は、1つのタブでインデントする必要があります。

(function( $ ) {
	// インデントされた式

	function doSomething() {
		// インデントされた式
	}
})( jQuery );
JavaScript
CopyExpand
Blocks and Curly Braces ブロックと中括弧

" if "、" else 、" for "、" while "、and " try " ブロックは常に中括弧{}を使用し、常に複数行に渡る必要があります。左中括弧は、関数定義、条件、またはループと同じ行にある必要があります。閉じ括弧は直接ブロックの最後の文の次の行にする必要があります。

var a, b, c;

if ( myFunction() ) {
	// 式
} else if ( ( a && b ) || c ) {
	// 式
} else {
	// 式
}
JavaScript
CopyExpand
Multi-line Statements 複数行のステートメント

文が長くて1行に収まらない場合には、改行は演算子の後に据える必要があります。

// これは悪い
var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c
	+ ' is ' + ( a + b + c );

// 良い
var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c +
	' is ' + ( a + b + c );
JavaScript
CopyExpand

読みやすさを向上させるのであれば、たとえ両方が1行に収まる場合でも、自らの一行の上でも各式に分割されている三項演算子のように、論理的なグループに分割する必要があります。

// 容認できる
var baz = ( true === conditionalStatement() ) ? 'thing 1' : 'thing 2';

// より良い
var baz = firstCondition( foo ) && secondCondition( bar ) ?
	qux( foo, bar ) :
	foo;
JavaScript
CopyExpand

条件が長くて1行に収まらない場合には、全体の中において連続する行を区別するために、1つレベルを追加してインデントされなければなりません。

	if ( firstCondition() & secondCondition() &
			thirdCondition() ) {
		doStuff();
	}
JavaScript
CopyExpand
Chained Method Calls 連鎖されたメソッド呼び出し

メソッド呼び出しのチェーンが1行に収まらない場合には、メソッドを呼び出すオブジェクトとは別の行の最初の呼び出しで、1行につき1つのコールを据えないといけません。この方法は、コンテキストを変更した場合、インデントの余分なレベルを使用する必要があります。

elements
	.addClass( 'foo' )
	.children()
		.html( 'hello' )
	.end()
	.appendTo( 'body' );
JavaScript
CopyExpand

≪ Assignments and Glovals ≫

Declaring Variables With var 変数宣言におけるvar

各関数は、必要とされるいくつかのローカルな変数の宣言である、単一のコンマ区切りの var ステートメントを伴って開始されるべきである。仮に関数が var を使用して変数の宣言をしない場合は、外側のスコープにもれたり(頻繁にグローバルスコープとなる最悪のシナリオ)知らず知らずのうちに参照され、そのデータは変更されることもある。

var ステートメントにおける代入は個別の行にてリストされるべきで、宣言においては一行でグループ化することができる。いずれの付加された行も付加されたタブによりインデントされなければならない。5行以上を占めるオブジェクトと関数においては、過度のインデントを避けるために、var ステートメントの外側で指定されるべきである。

// Good
var k, m, length,
	// ひとつのタブによりインデントされたその次の行
	value = 'WordPress';

// Bad
var foo = true;
var bar = false;
var a;
var b;
var c;
JavaScript
CopyExpand
Globals グローバル変数

過去においてWordPress のコアはグローバル変数を多用していました。コアJavaScriptファイルが時々プラグイン内で使用されているので、既存のグローバル変数は削除すべきではありません。
ファイル内で使用される全てのグローバル変数は、そのファイルの先頭において記述されるべきです。複数のグローバル変数はカンマで分けることができます。
この例はそのファイル内で許されたグローバル変数 passwordStrength を作る。

/* global passwordStrength:true */
JavaScript
CopyExpand

passwordStrength の後の true は、このグローバル変数が、このファイル内で定義されていることを意味しています。あなたが他の場所で定義されているグローバルにアクセスしている場合は、読み取り専用としてグローバル変数を指定するために :true を省略します。

Common Libraries 共通のライブラリ

ここの部分がわからなくて訳せないので原文も載せておきます。

Backbone, jQuery, Underscore, and the global wp object are all registered as allowed globals in the root .jshintrc file.
Backbone and Underscore may be accessed directly at any time. jQuery should be accessed through $ by passing the jQuery object into an anonymous function:

Backbone、jQuery、Underscore、そしてグローバルなwp オブジェクトは全て .jshintrc ファイルのルートにて許可されたグローバルとして登録されています。
Backbone、Underscorehaはいつでも直接にアクセスすることができます。jQuery は匿名関数に jQuery オブジェクトを渡すことで$ を介してアクセスされるべきです。

(function( $ ) {
  // Expressions
})( jQuery );
JavaScript
CopyExpand

This will negate the need to call .noConflict(), or to set $ using another variable. Files which add to, or modify, the wp object must safely access the global to avoid overwriting previously set properties:

このことは .noConflict() を呼び出したり、別の変数を使用して $ にセットする必要がなくなります。
ファイルに追加する、または変更すること、WPのオブジェクトは、あらかじめ設定されたプロパティが上書きされないように、グローバルに安全にアクセスする必要があります:

// At the top of the file, set &quot;wp&quot; to its existing value (if present)
window.wp = window.wp || {};
JavaScript
CopyExpand

≪ Naming Conventions 命名規則 ≫

変数名と関数名は、最初の文字には小文字を使用したキャメルケースを使用して、完全な単語である必要があります。この件においては、WordPressのPHPコーディング標準とこの規約とは異なる部分である。
new を用いてコンストラクタを使用する場合は、大文字の頭文字を使用するべきである(アッパーキャメルケース)。
名前はほどほどに説明的であるべきです。例外としては反復処理においてのループの指数を示すために使用されるような i に認められます。

≪ Comments コメント ≫

コメントはそれらが言及するコードの前に置き、常に空行が先にあるべきです。コメントの一文字目は大文字にし、完全な文章を書くときには最後にはピリオドを付けます。コメントトークン(//)とコメント文の間にはスペースが一つ必要です。
一行でのコメント

someStatement();

// Explanation of something complex on the next line
$( 'p' ).doSomething();
JavaScript
CopyExpand

複数行のコメントは長いコメントの扱いにする必要があります。

/*
This is a comment that is long enough to warrant being stretched
over the span of multiple lines.
*/
JavaScript
CopyExpand

Inline comments are allowed as an exception when used to annotate special arguments in formal parameter lists:

行の中のコメントにおいては、仮の引数リストの中の特別な引数の注釈として使用される時に例外として認められます。(formalの意味がよくわからない。)

function foo( types, selector, data, fn, /* INTERNAL */ one ) {
	// Do stuff
}
JavaScript
CopyExpand

≪ Equality 等価演算子 ≫

Strict equality checks (===) must be used in favor of abstract equality checks (==). The only exception is when checking for both undefined and null by way of null.

抽象的な等価演算子(==)は使いやすいが、厳格な同一演算子(===)が使用されなければならない。ただ一つの例外としては、「undefined」と「null」の両方を「null」を使用する方法において判別する時です。

// 多くの重要な理由において、「 undefined 」「 null 」の両方の値をチェックする
if ( undefOrNull == null ) {
	// 式
}
JavaScript
CopyExpand

≪ Type Checks 型チェック ≫

オブジェクトの型を確認するのに好ましい方法があります。

  • String: typeof object === 'string'
  • Number: typeof object === 'number'
  • Boolean: typeof object === 'boolean'
  • Object: typeof object === 'object' or _.isObject( object )
  • Plain Object: jQuery.isPlainObject( object )
  • Function: _.isFunction( object) or jQuery.isFunction( object )
  • Array: _.isArray( object ) or jQuery.isArray( object )
  • Element: object.nodeType or _.isElement( object )
  • null: object === null
  • null or undefined: object == null
  • undefined:
    • Global Variables: typeof variable === 'undefined'
    • Local Variables: variable === undefined
    • Properties: object.prop === undefined
    • Any of the above: _.isUndefined( object )

Backbone もしくは Underscore はどこでも既に使われています。あなたはUnderscore.js の型チェックメソッドをjQueryで使用することを奨励されます。

≪ Strings 文字列 ≫

文字列リテラルには単一引用符を使用します。

var myStr = 'strings should be contained in single quotes';
JavaScript
CopyExpand

文字列が単一引用符を含む時は、それらはバックスラッシュ(\)にてエスケープされる必要があります。

// 文字列内では単一引用符をエスケープする:
'Note the backslash before the \'single quotes\'';
JavaScript
CopyExpand

≪ Switch statements ≫

switch ステートメントの使用は、一般には反対されます。しかし、たくさんのケースがある時に、特に同じブロック内で複数のケースを扱える時に、もしくはロジックのフォールスルー(default のケース、case ブロックの通り抜け)を利用できることが重宝するかもしれません。
Switch ステートメントを使用する時は

  • default 以外の各ケースにおいて break を使用する。フォールスルーをステートメントに許可するときは、明示的に記述する。
  • switch 内において case は一つのタブでインデントする。
switch ( event.keyCode ) {

	// エンターキーとスペースキーのどちらもx() を起動する(フォールスルー)
	case $.ui.keyCode.ENTER:
	case $.ui.keyCode.SPACE:
		x();
		break;
	case $.ui.keyCode.ESCAPE:
		y();
		break;
	default:
		z();
}
JavaScript
CopyExpand

switch ステートメントの内部において値をリターンすることは推奨されない。case ブロックを使用して値をセットし、それから最後にそれらの値をリターンする。

function getKeyCode( keyCode ) {
	var result;

	switch ( event.keyCode ) {
		case $.ui.keyCode.ENTER:
		case $.ui.keyCode.SPACE:
			result = 'commit';
			break;
		case $.ui.keyCode.ESCAPE:
			result = 'exit';
			break;
		default:
			result = 'default';
	}

	return result;
}
JavaScript
CopyExpand

≪ Best Practices 最良なる実践 ≫

Arrays 配列

Javascript で配列を作成する時は、new Array() 表記ではなくショートハンド [] コンストラクタを使用するべきである。

var myArray = [];
JavaScript
CopyExpand

作成する時に配列を初期化することが出来ます。

var myArray = [ 1, 'WordPress', 2, 'Blog' ];
JavaScript
CopyExpand

Javascript においては、連想配列はオブジェクトとして定義されます。

Object オブジェクト

JavaScriptでオブジェクトを作成するにはいくつかの方法があります。オブジェクトリテラル表記は、{} 、最大のパフォーマンスであり、最も読みやすくもあります。

var myObj = {};
JavaScript
CopyExpand

オブジェクトが特定のプロトタイプを必要としない場合はオブジェクトリテラル表記が使用されるべきであり、特定のプロトタイプが必要とされる場合は new を用いてコンストラクタ関数を呼び出して作成されるべきです。

var myObj = new ConstructorMethod();
JavaScript
CopyExpand

オブジェクトのプロパティは、キーが変数ではない場合や予約後、もしくは文字列が有効な識別子では無い場合、ドット表記によってアクセスされるべきです。

prop = object.propertyName;
prop = object[ variableKey ];
prop = object['default'];
prop = object['key-with-hyphens'];
JavaScript
CopyExpand
"Yoda" Conditions ヨーダ条件式

PHP コーディング規約との一貫性をとるために、文字列、ブール値、数値もしくは他の定数やリテラルとオブジェクトを比較する時はいつでも、変数は常に右手に置かれるべきであり、定数やリテラルを左手に記述する。

if ( true === myCondition ) {
	// 行う事
}
JavaScript
CopyExpand

「少し異様、読むために、そのうち慣れる」

Iteration 繰り返し

多きなコレクションを for ループで繰り返す時に、その都度最大値を再計算するのではなく、ループの最大値を変数に格納することを推奨します。

// 良いし、能率的
var i, max;

// getItemCount() は一度だけ呼ばれる
for ( i = 0, max = getItemCount(); i < max; i++ ) {
	// 行う事
}

// 悪い 潜在的に能率が悪い:
// getItemCount() gets called every time
for ( i = 0; i < getItemCount(); i++ ) {
	// 行い
}
JavaScript
CopyExpand
Underscore.js Collection Functions

Underscore.js collection と array methods を学び理解しましょう。_.each、_.map、そして _.reduce を含むこれらの関数は、さらなる効率と大きなデータのセットにおいて読みやすい変換を可能にします。
Underscore もまた、通常のJavaScriptオブジェクトとのjQuery スタイルの連鎖をゆるします。

var obj = {
	first: 'thing 1',
	second: 'thing 2',
	third: 'lox'
};

var arr = _.chain( obj )
	.keys()
	.map(function( key ) {
		return key + ' comes ' + obj[ key ];
	})
	// Exit the chain
	.value();

// arr === [ 'first comes thing 1', 'second comes thing 2', 'third comes lox' ]
JavaScript
CopyExpand
Iterating Over jQuery collections

The only time jQuery should be used for iteration is when iterating over a collection of jQuery objects:

上の文、ちょっとわからない・・・jQuery オブジェクトのコレクションを反復処理するときに、一度だけのjQuery が反復に使用されるべきです。

$tabs.each(function( index, element ) {
	var $element = $( element );

	// Do stuff to $element
});
JavaScript
CopyExpand

生データやvanilla javascritp objects の反復にjQuery を使用してはいけない。

Principles of Writing Consistent, Idiomatic JavaScript一貫性のある慣用的な JavaScript の書き方

これ以下は『 Principles of Writing Consistent, Idiomatic JavaScript 』のページにある『一貫性のある慣用的な JavaScript の書き方』から。

Beautiful Syntax 美しい構文

A. 丸かっこ、中かっこ、改行

// if/else/for/while/try は常にスペース、中括弧、複数の行に架かるようにします。
// これは可読性を促進します。

if ( condition ) {
	// 文
}

while ( condition ) {
	//  文
}

for ( var i = 0; i < 100; i++ ) {
	// 文
}

// より良い例

var i,
	length = 100;
	
for ( i = 0; i < length; i++ ) {
	// 文
}

// または・・・

var i = 0,
	length = 100;

for ( ; i < length; i++ ) {
	// 文
}

var prop;

for ( prop in object ) {
	// 文
}

if ( true ) {
	// 文
} else {
	// 文
}
JavaScript
CopyExpand

B. 割り当て、宣言、関数(名前、式、コンストラクター)

// 変数
// 注:WordPress Javascript Standardにおいては文字列は単一引用符を使用する
var foo = "bar",
	num = 1,
	undef;

// リテラル表記
var array = [],
	object = {};

// 可読性を促進するためにスコープ(関数)ごとに一つだけ 'var' を使用します
// 宣言するリストはすっきりしている状態を保ちます(同様に少ないキーストロークを守ります)

// 悪い例
var foo = "";
var bar = "";
var qux;

// 良い例
var foo = "",
	bar = "",
	quux;

// または
var // ここにコメントをつけます
foo = "",
bar = "",
quux;

// var 文は常にそれぞれのスコープ(関数)の最初になくてはなりません。
// ECMAScript 6 のlet もまた同様です。

// 悪い例
function foo() {

	// ここにいくつかの文を書きます

	var bar = "",
		qux;
}

// 良い例
function foo() {
	var bar = "",
		qux;

	// すべの文は変数の宣言の後に書きます
}

// 名前付きの関数の宣言
function foo( arg1, argN ) {

}

// 関数の使い方
foo( arg1, argN );

// 名前付きの関数の宣言
function square( number ) {
	return number * number;
}

// 関数の使い方
square( 10 );

// 不自然に続けて渡すスタイル
function square( number, callback ) {
	callback( number * number );
}

square( 10, function( square ) ) {
	// コールバック関数の文
});

// 式による関数の宣言
var square = function( number ) {

	// 値や関連する何かを返します
	return number * number;
};

// 識別子と式による関数の宣言
// この望ましい形はスタックトレースの中で自ら呼び出せる識別子を
// 持てる値が追加されます
var factorial = function factorial( number ) {
	if ( number < 2 ) {
		return 1;
	}

	return number * factorial( number-1 );
};

// コンストラクターの宣言
function FooBar( options ) {

	this.options = options;
}

// コンストラクターの使い方
var fooBar = new FooBar({ a: "alpha" });

fooBar.options;
// { a: "alpha" }
JavaScript
CopyExpand

c. 例外や些細なこと

// コールバックと関数
foo(function() {
	// ここには実行される関数の最初の括弧と"function"との間には
	// スペースがないことを注意してください
});

// 配列を受け取る関数、スペースはなし
// WordPress Standard も同様
foo([ "alpha", "beta" ]);

// オブジェクトを受け取る関数、スペースなし
foo({
	a: "alpha",
	b: "beta"
});

//一つの文字列を受け取る場合、スペースなし
foo("bar");

// 中でグループ化された括弧、スペースなし
if ( ! ("foo" in obj) ) {

}
JavaScript
CopyExpand

D. 一貫性が常に勝つ
・・・省略・・・

E. クオート
あなたの好みがシングルクオートだろうとダブルクオートだろうとどうでもいい事です。これらはJavaScript の解析においては違いはありません。絶対に強制されることは一貫性につながります。同じプロジェクトの中でクオートを混ぜないでください。一つのスタイルを選び、それにこだわって下さい。

F. 行末と空行
スペースは読めない変更点を生み、差分を壊します。行末のスペースや空行のスペースを削除するためにコミット前の内容を組み込むかしっかり考えてください。

Type Checking (Courtesy jQuery Core Style Guidelines) 型のチェック

A. 実際の型
WordPress Javascript Coding Standard で既出 ≪ Type Checks 型チェック ≫を参照のこと

B. 強制された型
次の実装を考えて見てください。
こういうHTML があったとします。

<input type="text" id="foo-input" value="1">

// 'foo'は'0'という値で宣言されて、型は'number'になります。
var foo = 0;

// typeof foo;
// 'number'
・・・

// あなたのコードのどこかで、input要素から値を取得して
// 'foo'を更新する必要があります。

foo = document.getElementById("foo-input").value;

// もしあなたがこの時点で、'typeof foo' をテストした場合、次のような
// ロジックがあると、その結果は 'string' となることを意味します。
if ( foo === 1 ) {
	importantTask();
}
// 'importantTask()' はたとえ、'foo' が '1' だとしても評価されないでしょう。

//  + または - といった単項演算子を使って、強制的にこの問題を回避できます:
foo = +document.getElementById("foo-input").value;
// ^この + 演算子は右側の値をnumber に変換します。

// typeof foo;
// 'number"

if ( foo === 1 ) {
	importTask();
}
// こうすれば 'importTask()' は呼び出されます。
JavaScript
CopyExpand

これらは同じように強制的に変換するいくつかの方法です。

var number = 1,
	string = "1",
	bool = false;

number;
// 1

number + "";
// "1"

string;
// "1"

+string;
// 1

+string++;
// 1

string;
// 2

bool;
// false

+bool;
// 0

boo + "";
// "false"

var number = 1,
	string ="1",
	bool = true;

string === number;
// false

string === number + "";
// true

+string === number;
// true

bool === number;
// false

+bool === number;
// true

bool === string;
// false

bool === !!string;
//true

var array = [ "a", "b", "c" ];

!!~array.indexOf("a");
//true

!!~array.indexOf("b");
//true

!!~array.indexOf("c");
//true

!!~array.indexOf("d");
//false

// 上記は”無駄に考え過ぎていないか”ということを考慮してください。
// 次のような indexOf が返した値を明確に比較するようなアプローチにしてみましょう。
if ( array.indexOf( "a" ) >= 0) {
	// ・・・
}
JavaScript
CopyExpand
var num = 2.5;

parseInt( num, 10 );

// これは次の場合と同じです
~~num;

num >> 0;

num >>> 0;

// どれも結果は2になります。
// しかし、負の値の場合は異なった扱いをされること覚えておきましょう。

var neg = -2.5;

parseInt( neg, 10 );

// これは次の場合と同じです。

~~neg;

neg >> 0;

// これはどれも-2になります。
// 一方で・・・

neg >>> 0;

// この結果は4294967294となります
JavaScript
CopyExpand
Conditional Evaluation 条件分の評価
// 配列の長さだけを評価する場合は次の代わりに:
if ( array.length > 0 ) ...

// このように評価すればいいでしょう:
if ( array.length ) ...

// 配列が空かどうかだけを評価する場合は次の代わりに:
if ( array.length === 0 ) ...

// このように評価すればいいでしょう:
if ( ! array.length ) ...

// 文字列が空では無い事だけを評価する場合は次の代わりに:
if ( string !== "" ) ...

// このようにすればいいでしょう:
if ( string ) ...

// 文字列がからであることだけを評価する場合は次のかわりに:
if ( string === "" ) ...

// このようにすればいいでしょう:
if ( ! string ) ...

// 参照先が true がどうかだけ評価する場合は次の代わりに:
if ( foo === true ) ...

// このように評価することを意味し、これは内部的な機能を利用します:
if ( foo ) ...

// 参照先が false かどうかを評価する場合は次の代わりに:
if ( foo === false ) ...

// 強制的に true の評価を行うために否定を使います
if ( ! foo ) ...

// 注意点としてこの場合は、""、null、undefined、NaN といった値にも
// マッチします。もし false に限定する必要があるのであれば次のようにします
if ( foo ===false ) ...

// 参照先が false、""、0 ではなく、null または undefined かどうかだけを
// 評価する場合は次の代わりに:
if ( foo === null || foo === undefined ) ...

// 次のように == を使用して型の変換を利用します
if ( foo == null ) ...

// == は false 、""、0 ではなく null と undefined の両方を null とマッチすることを
// 覚えておいてください
null == undefined
JavaScript
CopyExpand

常にベストで正確な結果のための評価をしましょう - 上記はガイドラインであって、ドグマではありません。
注:ドグマとは・・・1.宗教上の教義。2.独断的な説。

// 型の変換と評価の注意書き
// '==' よりも '===' を選びましょう(ルーズな型の評価が必要でない限り)
// === は次のように型を変換しません:

"1" === 1;
// false

// == は次のように型を変換します:

"1" == 1;
// true

// ブール値、true な値と false な値が
// ブール値:
true,false

// true な値:
"foo",1

// false な値:
"", 0, null, undefined, NaN, void 0
JavaScript
CopyExpand
Practical Style 実際のスタイル
// 実際のモジュール

(function( global ) {
	var Module = (function() {

		var data = "secret";
	
		return {
			// 何かのブール値のプロパティ
			bool: true,
			// 何かの文字列の値
			string: "a string",
			// 配列のプロパティ
			array: [ 1, 2, 3, 4 ],
			// オブジェクトのプロパティ
			object: {
				lang: "en-Us"
			},
			getData: function() {
				// 現在の 'data' の値を取得する
				return data;
			},
			setData: function( value ) {
				// 'data' の値をセットしてそれを返す
				return ( data = value );
			}
		};
	})();
	
	// に可能性のあるものはここに
	
	// グローバルオブジェクトにモジュールを見えるようにします
	global.Module = Module;
})( this );

// 実際のコンストラクター

(function( global ) {

	function Ctor( foo ) {
		this.foo = foo;

		return this;
	}

	Ctor.prototype.getFoo = function() {
		return this.foo;
	};

	Ctor.prototype.setFoo = function( val ) {
		rerutn ( this.foo = val );
	};

	// 'new' を使わずにコンストラクターを呼び出すにはこのようにします:
	var ctor = function( foo ) {
		return new Ctor( foo );
	};

	// グローバルオブジェクトにモジュールを見えるようにします
	global.ctor = ctor;

})( this );
JavaScript
CopyExpand
Misc 雑則

このセクションは偏見的と見なされるべきではないアイデアやコンセプトを説明する代わりに、一般的なプログラミングタスクを行うためのより良い方法を見つけるためのプラクティスを助長するものです。

A. switch の使用はできるだけ避けるべきでモダンなメソッドトレースは switch 文をブラックリストの関数にするでしょう。

// switch 文の例
switch( foo ) {
	case "alpha":
		alpha();
		break;
	case "beta":
		beta();
		break;
	default:
		// デフォルトのための何か
		break;
}

// オブジェクトリテラルやモジュールを利用したより良いアプローチ
var switchObj = {
	alpha: function() {
		// 文
		// 返り値
	},
	beta: function() {
		// 文
		// 返り値
	},
	_default: function() {
		// 文
		// 返り値
	}
}

var switchModule = (function() {
	return {
		alpha: function() {
			// 文
			// 返り値
		},
		beta: function() {
			// 文
			// 返り値
		},
		_default: function() {
			// 文
			// 返り値
		}
	};
})();

// もし、'foo' が 'switchObj' または 'switchModule' のプロパティならメソッドとして実行されます。

( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args );

( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args );

// もし、'foo' の値がはっきり分かっているなら、OR のチェックを省いて
// 実行部分だけ残すようにできます。

switchObj[ foo ]( args );
switchModule[ foo ]( args );

// このパターンはコードの再利用性を促進します。
JavaScript
CopyExpand

B. ごくわずかなパフォーマンスと早く返り値を返すことでコードの可読性を促進します。

// 悪い例
function returnLate( foo ) {
	var ret;

	if ( foo ) {
		ret = "foo";
	} else {
		ret = "quux";
	}
	return ret;
}

// 良い例
function returnEarly( foo ) {
	if ( foo ) {
		return "foo";
	}
	return "quux";
}
JavaScript
CopyExpand
Naming ネーミング

A. あなたがコードをコンパイルしたり圧縮したりするわけではないので、そういった事をしようとしてはいけません。
次のコードはひどいネーミングの例です。

function q( s ) {
	return document.querySelectorAll(s);
}
var i,a=[],els=q("#foo");
for(i=0;i<else.length;i++){a.push(els[i]);}
JavaScript
CopyExpand

まぎれもなくこう書いた方がいいでしょう。
これはロジックは同じですが、より親切で考えられたネーミングです(そして読みやすい構造になっています。):

function query( selector ) {
	return document.querySelectorAll( selector );
}

var idx = 0,
	elements = [],
	matches = query("#foo"),
	length = matches.length;
	
for ( ; idx < length; idx++ ) {
	elements.push( matches[ idx ] );
}
JavaScript
CopyExpand

ネーミングの観点でいくつか補足すると

// 文字列のネーミング
 'dog' は文字列です。
 
 // 配列のネーミング
 'dogs''dog' という文字列の配列です
 
 // 関数、オブジェクト、インスタンスなどのネーミング
 camelCase; functionvar による宣言
 
 // コンストラクターやプロトタイプなどのネーミング
 PascalCase; コンストラクター
 
 // 正規表現のネーミング
 rDesc = //;
 
 // Google Closure Library Style Guide より
 
 functionNamesLikeThis;
 variableNamesLikeThis;
 ConstructorNamesLikeThis;
 EnumNamesLikeThis;
 methodNamesLikeThis;
 SYMBOLIC_CONSTANTS_LIKE_THIS;
JavaScript
CopyExpand

B. this の扱い
後から呼び出される BoundFunction を定義する場合は call や apply の一般的な使われ方よりも .bind( this ) や同等の機能が好ましいです。好ましいオプションがない場合だけ、別の方法を考えましょう。

function Device( opts ) {
 
 	this.value = null;
 
 	// これは非同期のストリームをオープンし
 	// 継続的に呼び出されます
 	stream.read( opts.path, function( data ) {
 
 		// このインスタンスの現在の値を
 		// データストリームの最新の値で更新します
 		this.value = data;

	}.bind(this) );

	// デバイスのインスタンスから頻繁に発行される
	// イベントを絞ります
	setInterval(function() {

		// 絞ったイベントを発行します
		this.emit("event");

	}.bind(this), opts.freq || 100 );
}

// EventEmitter を継承したかのように装います ;)
JavaScript
CopyExpand

もし利用できない場合でも最近の多くのJavaScript ライブライには .bind と同様な機能があります。

// 例)lodash/underscore の _.bind()
function Device( opts ) {

	this.value = null;

	stream.read( opts.path, _.bind(function( data ) {
		this.value = data;
	}, this) );
	setInterval(_.bind(function() {
		this.emit("event");
	}, this), opts.freq || 100 );
}

// 例)jQuery.proxy
function Device( opts ) {
	this.value = null;
	stream.read( opts.path, jQuery.proxy(function( data ) {
		this.value = data;
	}, this) );
	setInterval( jQuery.proxy(function() {
		this.emit("event");
	}, this), opts.freq || 100 );
}

// 例)dojo.hitch
function Device( opts ) {
	this.value = null;
	stream.read( opts.path, dojo.hitch( this, function( data ) {
		this.value = data;
	}) );
	setInterval( dojo.hitch( this, function() {
		this.emit("event");
	}), opts.freq || 100 );
}
JavaScript
CopyExpand

最後の回避方法は、識別子として this への別名に self を使うことですが、これは極端なバグになる傾向があるため、可能な限り避けるべきです。

function Device( opts ) {
	var self = this;
	this.valu = null;
	stream.read( opts.path, function( data ) {
		self.value = data;
	});
	setInterval(function() {
		self.emit("event");
	}), opts.freq || 100 );
}
JavaScript
CopyExpand

C. thisArg を使う
ES 5.1の各プロトタイプのメソッドでは特別な thisArg という署名に対応しています。これは可能な限り利用するべきです。

var obj;
obj = { f: "foo", b: "bar", q: "qux" };
object.keys( obj ).forEach(function( key ) {
	// |this| は 'obj' への参照
	console.log( this[ key ] );
}, obj );// <-- 最後の引数が 'thisArg'
// 結果は・・・

// "foo"
// "bar"
// "qux"
JavaScript
CopyExpand

thisArg は Array.prototype.every 、Array.prototype.forEach 、Array.prototype.some 、Array.prototype.map 、Array.prototype.filter と一緒に利用できます。

Native & Host Objects 以降は省略しました。

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=56652

Sanbanse Funabashi
2010.10.24 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。