Google JavaScript スタイルガイド - 日本語訳
http://w.atwiki.jp/aias-jsstyleguide2/
Google JavaScript スタイルガイド - 日本語訳
ja
2015-02-17T14:00:48+09:00
1424149248
-
JavaScriptのスタイルに関するルール
https://w.atwiki.jp/aias-jsstyleguide2/pages/15.html
#include_js(http://www38.atwiki.jp/aias-jsstyleguide2/?cmd=upload&act=open&page=%E3%83%88%E3%83%83%E3%83%97%E3%83%9A%E3%83%BC%E3%82%B8&file=goog_style_guide.js)
#divclass(page_title){
&this_page()
}
- 各項目の左側にある三角ボタン&html(<img src="http://www38.atwiki.jp/aias-jsstyleguide2/?cmd=upload&act=open&page=%E3%83%88%E3%83%83%E3%83%97%E3%83%9A%E3%83%BC%E3%82%B8&file=tri_down.gif" />)で、詳細情報の表示・非表示を切り替えられます。また下のボタンを使うと全項目を一度に変更することができます。
#divid(showhide_all){
&html(<div id="showhide_all_btn" class="show_dtl" ></div>)全て切り替える}
** &aname(naming,option=nolink){命名規則}
&html(<div id="shbtn_naming" class="show_dtl" ></div>)原則として、関数は&spanclass(keywd){functionNamesLikeThis}、変数は&spanclass(keywd){variableNamesLikeThis}、クラスは&spanclass(keywd){ClassNamesLikeThis}、列挙型は&spanclass(keywd){EnumNamesLikeThis}、メソッドは&spanclass(keywd){methodNamesLikeThis}、定数は&spanclass(keywd){CONSTANT_VALUES_LIKE_THIS}、名前空間は&spanclass(keywd){foo.namespaceNamesLikeThis.bar}、ファイルは&spanclass(keywd){filenameslikethis.js}のように、それぞれ命名してください。
#divid(dtl_naming){{{{
#divclass(dtl){{{
*** &aname(properties_and_methods,option=nolink){プロパティとメソッド}
- '''private''' なプロパティ、メソッドには名前の末尾にアンダースコアをつけてください。
- '''protected''' なプロパティ、メソッドには(publicと同様に)末尾にアンダースコアをつけません。
'''private''' と '''protected''' に関するより詳しい情報は、「&link_anchor(visibility){可視性}」の項を参照してください。
*** &aname(method_and_function_parameter,option=nolink){メソッドと関数のパラメータ}
省略可能な関数の引数は名前の先頭を&spanclass(keywd){opt_}としてください。
関数の引数の個数が可変である場合、最後の引数名は&spanclass(keywd){var_args}とすべきです。ただしコード内では&spanclass(keywd){var_args}を参照するのではなく、&spanclass(keywd){arguments}オブジェクトを使って下さい。
&spanclass(keywd2){@param}アノテーションによっても、省略可能な引数や個数の変化する引数を定義できます。Compilerは変数名とアノテーションのどちらの記法も受け入れますが、両者を共に使うのが好ましいやり方です。
*** &aname(getters_and_setters,option=nolink){GetterとSetter}
EcmaScript5では、プロパティに対するgetterとsetterは推奨されません。もし使うのなら、getterが監視中のプロパティの状態を変更しないようにしなければなりません。
#divclass(blockquote_ng){{{
#divclass(comment){{/**
 (1)* 間違い -- こうしてはいけません。
 (1)*/
}}
var foo = { get next() { return this.nextId++; } };
}}}
*** &aname(accessor_functions,option=nolink){アクセサ関数}
プロパティに対するgetterとsetterは必須ではありません。ただしそれを使う場合、getterは必ず&spanclass(keywd){getFoo()}、setterは必ず&spanclass(keywd){setFoo(value)}のように命名してください。(論理値を返すgetterであれば、&spanclass(keywd){isFoo()}としてもかまいません。たいていはその方が自然です。)
*** &aname(namespaces,option=nolink){名前空間}
JavaScript自体は、パッケージや名前空間の仕組みをサポートしていません。
グローバル名の衝突はデバックが難しく、また2つのプロジェクトを統合するようなケースでは、手に負えない大きな問題となる可能性もあります。JavaSriptコードの共有を可能にするには、衝突を防ぐための約束事に従う必要があります。
#divclass(subcaption){グローバルコードには名前空間を適用する}
グローバルスコープに存在するコードは''必ず''、プロジェクトやライブラリと関連付けられた一意のプリフィックスをもつ擬似的な名前空間に属しているものとします。もしプロジェクト名が "&spanclass(keywd){Project Sloth}" であれば、擬似的な名前空間名は&spanclass(keywd){sloth.*}とするのがよいでしょう:
#blockquote(){{var sloth = {};
sloth.sleep = function() {
 (2)...
};
}}
&blanklink(Closure Library){http://code.google.com/closure/library/}や&blanklink(Dojo Toolkit){http://www.dojotoolkit.org/}を含む多くのライブラリは、名前空間を宣言するための高位の関数が提供されています。名前空間の宣言方法には一貫性を持たせてください:
#blockquote(){{goog.provide('sloth');
sloth.sleep = function() {
 (2)...
};
}}
#divclass(subcaption){名前空間の所有権を尊重する}
ある名前空間の下位の名前空間で何かをする場合は、必ず親の名前空間の所有者にそのことを知らせてください。もしあなたが&spanclass(keywd){sloth}の下に&spanclass(keywd){hats}を作ろうとしているのであれば、Slothチームはあなたが使う&spanclass(keywd){sloth.hats}のことを必ず知っていなければなりません。
#divclass(subcaption){外部コードと内部コードでは異なる名前空間を使う}
「外部コード」とは、あなたのコードベースの外部にあり、独立してコンパイルされた全てのコードのことです。外部コードと内部コードで使われている名前は、厳格に分離されなければなりません。もしあなたが&spanclass(keywd){foo.hats.*}という名前で提供される外部ライブラリを使っているのなら、内部コードは&spanclass(keywd){foo.hats.*}にいかなるシンボルも定義してはいけません。ライブラリの提供元が新しいシンボルを定義すると、そのコードは動作しなくなるおそれがあるからです:
#divclass(blockquote_ng){{{
foo.require('foo.hats');
#divclass(comment){{/**
 (1)* 間違い -- こうしてはいけません。
 (1)* &spanclass(doctag){@constructor}
 (1)* &spanclass(doctag){@extends} {foo.hats.RoundHat}
 (1)*/
}}
foo.hats.BowlerHat = function() {
};
}}}
どうしても外部コードの名前空間に新しいAPIを追加する必要がある場合は、そのAPI関数だけを明示的にエクスポートしてください。ただしそうであっても、一貫性を保ち、Compilerがより効果的に最適化を行えるようにするため、内部コードは内部の名前で内部のAPIを呼び出すようにすべきです。
#blockquote(){{{foo.provide('googleyhats.BowlerHat');
foo.require('foo.hats');
#divclass(comment){{/**
 (1)* &spanclass(doctag){@constructor}
 (1)* &spanclass(doctag){@extends} {foo.hats.RoundHat}
 (1)*/
}}
googleyhats.BowlerHat = function() {
 (2)...
};
goog.exportSymbol('foo.hats.BowlerHat', googleyhats.BowlerHat);
}}}
#divclass(subcaption){可読性を上げるため長い名前に別名を付ける}
もしそうすることで可読性が向上するなら、完全な型名に対しローカルの別名を付けましょう。ローカル名は型の一番最後の部分にマッチするようにしてください:
#blockquote(){{{#divclass(comment){{/**
 (1)* &spanclass(doctag){@constructor}
 (1)*/
}}
some.long.namespace.MyClass = function() {
};
#divclass(comment){{/**
 (1)* &spanclass(doctag){@param} {some.long.namespace.MyClass} a
 (1)*/
}}
some.long.namespace.MyClass.staticHelper = function(a) {
 (2)...
};
myapp.main = function() {
 (2)var MyClass = some.long.namespace.MyClass;
 (2)var staticHelper = some.long.namespace.MyClass.staticHelper;
 (2)staticHelper(new MyClass());
};
}}}
名前空間にローカルの別名をつけてはいけません。名前空間への別名付けには&link_anchor(aliasing_with_goog_scope){goog.scope}を使いましょう。
#divclass(blockquote_ng){{
myapp.main = function() {
 (2)var namespace = some.long.namespace;
 (2)namespace.MyClass.staticHelper(new namespace.MyClass());
};
}}
プロパティが列挙型である場合を除き、別名のプロパティ(やその他のメンバ)へのアクセスは避けて下さい:
#blockquote(){{{#divclass(comment){{/** &spanclass(doctag){@enum} {string} */
}}
some.long.namespace.Fruit = {
 (2)APPLE: 'a',
 (2)BANANA: 'b'
};
myapp.main = function() {
 (2)var Fruit = some.long.namespace.Fruit;
 (2)switch (fruit) {
 (4)case Fruit.APPLE:
 (6)...
 (4)case Fruit.BANANA:
 (6)...
 (4)}
};
}}}
#divclass(blockquote_ng){{
myapp.main = function() {
 (2)var MyClass = some.long.namespace.MyClass;
 (2)MyClass.staticHelper(null);
};
}}
グローバルスコープでの別名の作成は絶対にしないでください。別名は関数ブロックの中でのみ使用可能とします。
***&aname(filenames,option=nolink){ファイル名の命名規則}
大文字小文字を区別するプラットフォームで混乱が生じることを避けるため、ファイル名には小文字のみを使って下さい。ファイル名は&spanclass(keywd){.js}で終わらねばならず、&spanclass(keywd){-}と&spanclass(keywd){_}以外の区切り文字を含んではいけません(より好ましいのは&spanclass(keywd){_}より&spanclass(keywd){-}の方です)。
}}}
}}}}
** &aname(custom_tostring_methods,option=nolink){独自のtoString()メソッド}
&html(<div id="shbtn_custom_tostring_methods" class="show_dtl" ></div>)副作用なしで常に成功すること。
#divid(dtl_custom_tostring_methods){{{
#divclass(dtl){{
独自の&spanclass(keywd){toString()}メソッドを定義することで、オブジェクトが自分自身を文字列化(string-ify)する方法を制御できます。それ自体はよいのですが、そのときメソッドは以下の点を保証していなければなりません。(1) 常に成功すること、(2)他の部分に影響を与えないこと。この基準を満たしていない場合、容易に深刻な問題が引き起こされることでしょう。例えば&spanclass(keywd){toString()}メソッドが内部で&spanclass(keywd){assert}関数を呼び出しているとします。&spanclass(keywd){assert}は処理が失敗した場合にオブジェクト名を出力しようとしますが、その時に呼び出すのはもちろん&spanclass(keywd){toString()}メソッドです。
}}
}}}
** &aname(deferred_initialization,option=nolink){変数初期化の遅延}
&html(<div id="shbtn_deferred_initialization" class="show_dtl" ></div>)OK。
#divid(dtl_deferred_initialization){{
#divclass(dtl){
変数は、宣言された時点で常に初期化が可能とは限りません。従って初期化の遅延は当然ありうることです。
}
}}
** &aname(explicit_scope,option=nolink){明示的なスコープ}
&html(<div id="shbtn_explicit_scope" class="show_dtl" ></div>)常にそうしてください。
#divid(dtl_explicit_scope){{{
#divclass(dtl){{
常に明示的なスコープを使用し、移植性と明瞭さを向上させてください。例えば関数を作るとき、スコープチェーンの中に&spanclass(keywd){window}があることを仮定しないでください。いつか&spanclass(keywd){window}がコンテントウィンドウを指していない別のアプリケーションでそれを使いたくなるかもしれません。
}}
}}}
** &aname(code_formatting,option=nolink){コードのフォーマット}
&html(<div id="shbtn_code_formatting" class="show_dtl" ></div>)詳しい情報を見るには開いてください。
#divid(dtl_code_formatting){{{{{
#divclass(dtl){{{{
基本的な考え方は[[C++ formatting rules>>http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Formatting]]に従い、さらに以下に説明する内容が追加されます。
*** &aname(curly_braces,option=nolink){波括弧}
セミコロンの暗黙的な挿入を考慮し、波括弧を開くときはそれまでと同じ行で始めてください。例えばこのようにします:
#blockquote(){{{if (something) {
 (2)&spanclass(comment){// ...}
} else {
 (2)&spanclass(comment){// ...}
}
}}}
*** &aname(array_and_object_initializers,option=nolink){配列とオブジェクトの初期化}
きれいに収まるようなら、配列やオブジェクトの初期化を1行で行ってもかまいません:
#blockquote(){{{var arr = [1, 2, 3]; &spanclass(comment){// [の後と]の前にスペースを入れないでください。}
#html2(){{
var obj = {a: 1, b: 2, c: 3}; <span class="comment" >// {の後と}の前にスペースを入れないでください。</span>
}}
}}}
配列とオブジェクトの初期化が複数行にわたる場合は、ブロックと同様、括弧を変数と同じ行に置き、スペース2つ分インデントしてください:
#blockquote(){{{&spanclass(comment){// オブジェクトの初期化}
var inset = {
 (2)top: 10,
 (2)right: 20,
 (2)bottom: 15,
 (2)left: 12
};
&spanclass(comment){// 配列の初期化}
this.rows_ = [
 (2)'"Slartibartfast" <&nolink(fjordmaster@magrathea.com)>',
 (2)'"Zaphod Beeblebrox" <&nolink(theprez@universe.gov)>',
 (2)'"Ford Prefect" <&nolink(ford@theguide.com)>',
 (2)'"Arthur Dent" <&nolink(has.no.tea@gmail.com)>',
 (2)'"Marvin the Paranoid Android" <&nolink(marv@googlemail.com)>',
 (2)'&nolink(the.mice@magrathea.com)'
];
&spanclass(comment){// メソッド呼び出しの中で使う例。}
goog.dom.createDom(goog.dom.TagName.DIV, {
 (2)id: 'foo',
 (2)className: 'some-css-class',
 (2)style: 'display:none'
}, 'Hello, world!');
}}}
初期化リストの中で長い識別子や値の位置を揃えるのはやっかいな問題です。むしろ常に位置を揃えない方がよいでしょう。例えばこのようにします:
#blockquote(){{CORRECT_Object.prototype = {
 (2)a: 0,
 (2)b: 1,
 (2)lengthyName: 2
};
}}
下のようにはしません:
#divclass(blockquote_ng){{
WRONG_Object.prototype = {
 (2)a (10): 0,
 (2)b (10): 1,
 (2)lengthyName: 2
};
}}
*** &aname(function_arguments,option=nolink){関数の引数}
可能であれば、関数の引数リストは全て同じ行に書かれるべきです。もしそうすることで80文字の制限を超えてしまう場合、引数は読みやすい形式で改行されなくてはなりません。可能な限り80文字に近づけてスペースを節約するか、または引数ごとに改行を行って可読性を高めます。インデントはスペース4つ分、もしくは丸括弧で位置を揃えます。以下に示す例は引数を改行する際の最も一般的なパターンです:
#blockquote(){{{&spanclass(comment){// スペース4つ分インデントし、80文字で折り返します。関数名がとても長い場合に使います。}
&spanclass(comment){// 関数名が変わったときにインデントを修正する必要がなく、場所もあまりとりません。}
goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
 (4)veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
 (4)tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
 (2)&spanclass(comment){// ...}
};
#divclass(comment){
&nolink()// スペース4つ分インデントし、各行に1つずつ引数を書きます。関数名が長い場合に使います。
&nolink()// 関数名の変更の影響を受けず、また個々の引数を目立たせることができます。
}
goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
 (4)veryDescriptiveArgumentNumberOne,
 (4)veryDescriptiveArgumentTwo,
 (4)tableModelEventHandlerProxy,
 (4)artichokeDescriptorAdapterIterator) {
 (2)&spanclass(comment){// ...}
};
#divclass(comment){
&nolink()// 丸括弧に揃えてインデントし、80文字で折り返します。視覚的に引数をグループ化でき、
&nolink()// かつスペースも少なくてすみます。
}
function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
 (13)tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
 (2)&spanclass(comment){// ...}
}
#divclass(comment){
&nolink()// 丸括弧に揃えてインデントし、各行に1つずつ引数を書きます。
&nolink()// 個々の引数を目立たせることができます。
}
function bar(veryDescriptiveArgumentNumberOne,
 (13)veryDescriptiveArgumentTwo,
 (13)tableModelEventHandlerProxy,
 (13)artichokeDescriptorAdapterIterator) {
 (2)&spanclass(comment){// ...}
}
}}}
関数の呼び出し自体がインデントされている場合、元の文もしくは関数呼び出しの開始位置を基準にスペース4つ分インデントしてかまいません。次の例は全て許容されるスタイルです:
#blockquote(){{if (veryLongFunctionNameA(
 (8)veryLongArgumentName) ||
 (4)veryLongFunctionNameB(
 (4)veryLongArgumentName)) {
 (2)veryLongFunctionNameC(veryLongFunctionNameD(
 (6)veryLongFunctioNameE(
 (10)veryLongFunctionNameF)));
}
}}
*** &aname(passing_nonymous_functions,option=nolink){無名関数の引渡し}
関数呼び出しの引数リスト内で無名関数を宣言する場合、無名関数の内容は、文全体の左端からスペース2つ分、もしくは無名関数の宣言の左端からスペース2つ分インデントします。これは無名関数の内容を読みやすくする(関数全体が画面の右側に圧し潰された状態にならないようにする)ためです。
#blockquote(){{prefix.something.reallyLongFunctionName('whatever', function(a1, a2) {
 (2)if (a1.equals(a2)) {
 (4)someOtherLongFunctionName(a1);
 (2)} else {
 (4)andNowForSomethingCompletelyDifferent(a2.parrot);
 (2)}
});
var names = prefix.something.myExcellentMapFunction(
 (4)verboselyNamedCollectionOfItems,
 (4)function(item) {
 (6)return item.name;
 (4)});
}}
*** &aname(aliasing_with_goog_scope,option=nolink){goog.scopeによる別名}
&blanklink(Closure Library){https://developers.google.com/closure/library/}が提供する&blanklink(goog.scope){https://docs.google.com/document/pub?id=1ETFAuh2kaXMVL-vafUYhaWlhl6b5D9TOvboVg7Zl68Y}を使うと、名前空間を含むシンボルの長い名前を短く置き換えることができます。
&spanclass(keywd2){goog.scope}の呼び出しは、1ファイルにつき1度だけ、グローバルスコープ内で行います。
呼び出しの開始部分&spanclass(keywd){goog.scope(function() {}は、&spanclass(keywd){goog.provide}、&spanclass(keywd){goog.require}、トップレベルコメントの後に、正確に1行空けてから記述しなければなりません。呼び出しはファイルの最終行で閉じられなければなりません。またこのとき&spanclass(keywd){// goog.scope}というコメントを、ステートメント末尾のセミコロンからスペース2つ空けて追記してください。
C++の名前空間と同様に、&spanclass(keywd){goog.scope}の配下のコードはインデントしません。各行の先頭から記述を続けます。
作成した別名を、別のオブジェクト(例えば、ほとんどのコンストラクタ、列挙型、名前空間)へ再割り当てしないでください。次のようにしてはいけません(コンストラクタへの別名のつけ方は、下を参照してください):
#divclass(blockquote_ng){{
goog.scope(function() {
var Button = goog.ui.Button;
Button = function() { ... };
...
}}
別名は、シンボルの完全名の最後の部分と同じでなければなりません。
#blockquote(){{{goog.provide('my.module.SomeType');
goog.require('goog.dom');
goog.require('goog.ui.Button');
goog.scope(function() {
var Button = goog.ui.Button;
var dom = goog.dom;
&spanclass(comment){// コンストラクタ宣言より後に別名化します。}
my.module.SomeType = function() { ... };
var SomeType = my.module.SomeType;
&spanclass(comment){// いつもどおり、プロトタイプメソッドを宣言します:}
SomeType.prototype.findButton = function() {
 (1)&spanclass(comment){// 上で別名化したButton}
 (2)this.button = new Button(dom.getElement('my-button'));
};
...
}); &spanclass(comment){// goog.scope}
}}}
*** &aname(indenting_wrapped_lines,option=nolink){行折り返しのインデント}
&link_anchor(array_and_object_literals,pageid=13){配列リテラルとオブジェクトリテラル}、無名関数を除き、行の折り返しは全て'兄弟'の式に対し左揃えでインデントするか、'親'の式に対しスペース4つ(2つではなく)分深くインデントします(ここでいう'兄弟'や'親'は、丸括弧のネストの深さを指します)。
#blockquote(){{someWonderfulHtml = '' +
 (20)getEvenMoreHtml(someReallyInterestingValues, moreValues,
 (36)evenMoreParams, 'a duck', true, 72,
 (36)slightlyMoreMonkeys(0xfff)) +
 (20)'';
thisIsAVeryLongVariableName =
 (4)hereIsAnEvenLongerOtherFunctionNameThatWillNotFitOnPrevLine();
thisIsAVeryLongVariableName = siblingOne + siblingTwo + siblingThree +
 (4)siblingFour + siblingFive + siblingSix + siblingSeven +
 (4)moreSiblingExpressions + allAtTheSameIndentationLevel;
thisIsAVeryLongVariableName = operandOne + operandTwo + operandThree +
 (4)operandFour + operandFive * (
 (8)aNestedChildExpression + shouldBeIndentedMore);
someValue = this.foo(
 (4)shortArg,
 (4)'Some really long string arg - this is a pretty common case, actually.',
 (4)shorty2,
 (4)this.bar());
if (searchableCollection(allYourStuff).contains(theStuffYouWant) &&
 (4)!ambientNotification.isActive() && (client.isAmbientSupported() ||
 (40)client.alwaysTryAmbientAnyways())) {
 (2)ambientNotification.activate();
}
}}
*** &aname(blank_lines,option=nolink){空行}
論理的に関連性のあるコードをまとめるため、空行を使ってください。例えば次のようにします:
#blockquote(){{doSomethingTo(x);
doSomethingElseTo(x);
andThen(x);
nowDoSomethingWith(y);
andNowWith(z);
}}
*** &aname(binary_and_ternary_operators,option=nolink){二項または三項の演算子}
演算子は必ず先行する行の側に置きます。それを除くと、改行やインデントは他のGoogleスタイルガイドと同じルールに従います。当初この演算子の配置はセミコロンの自動挿入への配慮から決定されましたが、実際にはセミコロンが二項演算子の前に挿入されることはありません。しかし一貫性を保つため、新しいコードもこのスタイルを守ってください。
#blockquote(){{var x = a ? b : c; &spanclass(comment){// 収まるなら1行にまとめます。}
&spanclass(comment){// 4文字分のインデントはOKです。}
var y = a ?
 (4)longButSimpleOperandB : longButSimpleOperandC;
&spanclass(comment){// 最初のオペランドの位置までインデントするのもOKです。}
var z = a ?
 (8)moreComplicatedB :
 (8)moreComplicatedC;
}}
ドット演算子も同じです。
#blockquote(){{var x = foo.bar().
 (4)doSomething().
 (4)doSomethingElse();
}}
}}}}
}}}}}
** &aname(parentheses,option=nolink){丸括弧}
&html(<div id="shbtn_parentheses" class="show_dtl" ></div>)必要なときだけ使います。
#divid(dtl_parentheses){{{
#divclass(dtl){{
丸括弧は控えめに、基本的には文法やセマンティクスが求める場合にだけ使います。
&spanclass(keywd2){delete}、&spanclass(keywd){typeof}、&spanclass(keywd){void}のような単項演算子や&spanclass(keywd){return}、&spanclass(keywd){throw}のようなキーワードの後ろで丸括弧を使ってはいけません(&spanclass(keywd){case}、&spanclass(keywd){in}、&spanclass(keywd){new}で使わないのと同様です)。
}}
}}}
** &aname(strings,option=nolink){文字列}
&html(<div id="shbtn_strings" class="show_dtl" ></div>) ()&spanclass(keywd){"}より&spanclass(keywd){'}を使います。
#divid(dtl_strings){{{
#divclass(dtl){{
一貫性の点で、ダブルクォート(&spanclass(keywd){"})よりもシングルクォート(&spanclass(keywd){'})の方が好ましいといえます。HTMLを含む文字列を作成する際には、シングルクォートの方が便利です:
#blockquote(){var msg = 'This is some HTML';
}
}}
}}}
** &aname(visibility,option=nolink){可視性(privateまたはprotectedなフィールド)}
&html(<div id="shbtn_visibility" class="show_dtl" ></div>)JSDocアノテーションの&spanclass(keywd){@private}と&spanclass(keywd){@protected}の利用を推奨します。
#divid(dtl_visibility){{{{{
#divclass(dtl){{{{
JSDocアノテーションの&spanclass(keywd){@private}と&spanclass(keywd){@protected}を利用し、クラス、関数、プロパティの可視性を明示することを推奨します。
Compilerのフラグ&spanclass(keywd){--jscomp_warning=visibility}を有効にすると、可視性の違反について警告が出力されます。[[Closure Compiler Warnings>>http://code.google.com/p/closure-compiler/wiki/Warnings]]を参照してください。
グローバルな変数や関数に付けられた&spanclass(keywd){@private}は、同じファイル内のコードだけがそれらにアクセス可能であることを表します。
&spanclass(keywd2){@private}が付けられたコンストラクタは、それをインスタンス化できるのが同じファイル内のコードとそれ自身の静的またはインスタンスメンバだけであることを表します。&spanclass(keywd){@private}コンストラクタは、同じファイルからであればパブリックで静的なプロパティとしてアクセスできます。また&spanclass(keywd){instanceof}演算子もそれらにアクセスできます。
グローバルな変数、関数、コンストラクタに対して&spanclass(keywd){@protected}アノテーションは絶対に付けられません。
#blockquote(){{{&spanclass(comment){// ファイル 1}
#divclass(comment){{
&nolink()// AA_PrivateClass_ と AA_init_ はグローバルでありかつ同一ファイル内に存在するため、
&nolink()// 互いにアクセス可能です。
}}
#divclass(comment){{
/**
 (1)* &spanclass(doctag){@private}
 (1)* &spanclass(doctag){@constructor}
 (1)*/
}}
AA_PrivateClass_ = function() {
};
#divclass(comment){{
/** &spanclass(doctag){@private} */
}}
function AA_init_() {
 (2)return new AA_PrivateClass_();
}
AA_init_();
}}}
&spanclass(keywd2){@private}なプロパティにアクセス可能なのは、同じファイルに存在する全てのコードと、もしそのプロパティがクラスに属しているのであれば、そのプロパティを"所有"するクラスの全ての静的メソッドとインスタンスメソッドです。それらは別のファイルに存在するサブクラスからはアクセスできず、オーバーライドされることもありません。
&spanclass(keywd2){@protected}なプロパティにアクセス可能なのは、同じファイルに存在する全てのコードと、そのプロパティを"所有"するクラスとそのサブクラスの全ての静的メソッドとインスタンスメソッドです。
これらのセマンティクスはC++やJavaのそれとは違いがある点に注意してください。例えばアクセス権限は、同じクラスやクラス階層に属するものだけでなく、同じファイル内に存在する全てのコードに与えられています。またC++とは異なり、プライベートなプロパティはサブクラスからオーバーライドできません。
#blockquote(){{{&spanclass(comment){// ファイル 1}
#divclass(comment){{
/** &spanclass(doctag){@constructor} */
}}
AA_PublicClass = function() {
#divclass(comment){{
 (2)/** &spanclass(doctag){@private} */
}}
 (2)this.privateProp_ = 2;
#divclass(comment){{
 (2)/** &spanclass(doctag){@protected} */
}}
 (2)this.protectedProp = 4;
};
#divclass(comment){{
/** &spanclass(doctag){@private} */
}}
AA_PublicClass.staticPrivateProp_ = 1;
#divclass(comment){{
/** &spanclass(doctag){@protected} */
}}
AA_PublicClass.staticProtectedProp = 31;
#divclass(comment){{
/** &spanclass(doctag){@private} */
}}
AA_PublicClass.prototype.privateMethod_ = function() {};
#divclass(comment){{
/** &spanclass(doctag){@protected} */
}}
AA_PublicClass.prototype.protectedMethod = function() {};
#divclass(comment){{
&nolink()// ファイル 2
/**
 (1)* &spanclass(doctag){@return} {number} 1列に並べたカモの数。
 (1)*/
}}
AA_PublicClass.prototype.method = function() {
 (1)&spanclass(comment){// これら2つのプロパティへのアクセスは正当です。}
 (2)return this.privateProp_ + AA_PublicClass.staticPrivateProp_;
};
#divclass(comment){{
&nolink()// ファイル 3
/**
 (1)* &spanclass(doctag){@constructor}
 (1)* &spanclass(doctag){@extends} {AA_PublicClass}
 (1)*/
}}
AA_SubClass = function() {
 (1)&spanclass(comment){// protectedな静的プロパティへの正当なアクセス。}
 (2)AA_PublicClass.staticProtectedProp = this.method();
};
goog.inherits(AA_SubClass, AA_PublicClass);
#divclass(comment){{
/**
 (1)* &spanclass(doctag){@return} {number} 1列に並べたカモの数。
 (1)*/
}}
AA_SubClass.prototype.method = function() {
 (1)&spanclass(comment){// protectedなインスタンスプロパティへの正当なアクセス。}
 (2)return this.protectedProp;
};
}}}
JavaScriptでは、ある型(&spanclass(keywd){AA_PrivateClass_}のような)とその型のコンストラクタが区別されないことに注意してください。publicな型とprivateなコンストラクタを両立させる方法はありません。(可視性のチェックを破ってコンストラクタに別名をつけるのは簡単だからです)
}}}}
}}}}}
** &aname(js_types,option=nolink){JavaScriptのデータ型}
&html(<div id="shbtn_js_types" class="show_dtl" ></div>)Compilerによる型の強制を推奨します。
#divid(dtl_js_types){{{
#divclass(dtl){{
詳細は&link(こちらのページ){JavaScriptのデータ型}を参照してください。
}}
}}}
**&aname(comments,option=nolink){コメント}
&html(<div id="shbtn_comments" class="show_dtl" ></div>)JSDocを使ってください。
#divid(dtl_comments){{{
#divclass(dtl){{
詳細は&link(こちらのページ){JSDocコメント}を参照してください。
}}
}}}
**&aname(providing_dependencies_with_goog_provide,option=nolink){goog.provideによる依存関係の規定}
&html(<div id="shbtn_providing_dependencies_with_goog_provide" class="show_dtl" ></div>)トップレベルのシンボルだけを規定します。
#divid(dtl_providing_dependencies_with_goog_provide){{{{
#divclass(dtl){{{
あるクラスに含まれるメンバ(列挙型や内部クラスなど)は全て、同じファイル内で定義しましょう。こうすると、1つのファイル内でgoog.provideが規定するのは最上位のクラスだけになるはずです。
こうします:
#blockquote(){{goog.provide('namespace.MyClass');
}}
こうはしません:
#divclass(blockquote_ng){{
goog.provide('namespace.MyClass');
goog.provide('namespace.MyClass.Enum');
goog.provide('namespace.MyClass.InnerClass');
goog.provide('namespace.MyClass.TypeDef');
goog.provide('namespace.MyClass.CONSTANT');
goog.provide('namespace.MyClass.staticMethod');
}}
名前空間のメンバは個々に規定します:
#blockquote(){{goog.provide('foo.bar');
goog.provide('foo.bar.method');
goog.provide('foo.bar.CONSTANT');
}}
}}}
}}}}
** &aname(compiling,option=nolink){コンパイル}
&html(<div id="shbtn_compiling" class="show_dtl" ></div>)必須です。
#divid(dtl_compiling){{{
#divclass(dtl){{
クライアントに配信される全てのコードは、&blanklink(Closure Compiler){http://code.google.com/closure/compiler/}のようなJSコンパイラによってコンパイルされていなければなりません。
}}
}}}
** &aname(tips_and_tricks,option=nolink){ヒントとテクニック}
&html(<div id="shbtn_tips_and_tricks" class="show_dtl" ></div>)JavaScriptについてもう少しだけ。
#divid(dtl_tips_and_tricks){{{{{
#divclass(dtl){{{{
*** &aname(boolean_expressions,option=nolink){論理値表現}
以下の値は、論理値の表現としてはすべてfalseです:
- &spanclass(keywd2){null}
- &spanclass(keywd2){undefined}
- &spanclass(keywd2){''}(空文字)
- 数値の&spanclass(keywd){0}
でも気をつけてください。以下の値は全てtrueです:
- 文字列の&spanclass(keywd){'0'}
- &spanclass(keywd2){[]}(空の配列)
- &spanclass(keywd2){{}}(空のオブジェクト)
以上から、下のコードを書き換えてみましょう:
#divclass(blockquote_ng){{
while (x != null) {
}}
これはもっと短くできます(ただし&spanclass(keywd){x}が 0、空文字、falseを取らないことが条件です):
#blockquote(){{while (x) {
}}
また、文字列がnullでも空文字でもないことをチェックしたいとします。こうも書けますが:
#divclass(blockquote_ng){{
if (y != null && y != '') {
}}
下の方が短くてもっといいでしょう:
#blockquote(){{if (y) {
}}
警告: 論理値表現の結果は直感と異なることがよくあります。いくつか例を示します:
- &spanclass(keywd2){Boolean('0') == true&br()'0' != true}
- &spanclass(keywd2){0 != null&br()0 == []&br()0 == false}
- &spanclass(keywd2){Boolean(null) == false&br()null != true&br()null != false}
- &spanclass(keywd2){Boolean(undefined) == false&br()undefined != true&br()undefined != false}
- &spanclass(keywd2){Boolean([]) == true&br()[] != true&br()[] == false}
- &spanclass(keywd2){Boolean({}) == true&br(){} != true&br(){} != false}
*** &aname(conditional_ternary_operator,option=nolink){条件(三項)演算子} (?:)
こう書く代わりに:
#blockquote(){{if (val) {
 (2)return foo();
} else {
 (2)return bar();
}
}}
こう書くことができます:
#blockquote(){{return val ? foo() : bar();
}}
三項演算子はHTMLを作成するときにも便利です:
#blockquote(){{var html = '<input type="checkbox"' +
 (4)(isChecked ? ' checked' : '') +
 (4)(isEnabled ? '' : ' disabled') +
 (4)' name="foo">';
}}
*** &aname(and_and_or,option=nolink){&& と ||}
これらの二項演算子は短絡演算子です。最後に評価された項目の結果を式全体の評価とします。
&spanclass(keywd2){||}は「デフォルト」演算子とも呼ばれます。その理由は:
#divclass(blockquote_ng){{{
#divclass(comment){{/** &spanclass(doctag){@param} {*=} opt_win */}}
function foo(opt_win) {
 (2)var win;
 (2)if (opt_win) {
 (4)win = opt_win;
 (2)} else {
 (4)win = window;
 (2)}
 (1)&spanclass(comment){// ...}
}
}}}
上のコードを、こう書き換えられるからです:
#blockquote(){{{#divclass(comment){{/** &spanclass(doctag){@param} {*=} opt_win */}}
function foo(opt_win) {
 (2)var win = opt_win || window;
 (1)&spanclass(comment){// ...}
}
}}}
&spanclass(keywd2){&&}もまた、コードを短くするのに役立ちます。例えば下のように書く代わりに:
#divclass(blockquote_ng){{
if (node) {
 (2)if (node.kids) {
 (4)if (node.kids[index]) {
 (6)foo(node.kids[index]);
 (4)}
 (2)}
}
}}
こうできます:
#blockquote(){{if (node && node.kids && node.kids[index]) {
 (2)foo(node.kids[index]);
}
}}
あるいは:
#blockquote(){{var kid = node && node.kids && node.kids[index];
if (kid) {
 (2)foo(kid);
}
}}
とはいえ、これは少々やりすぎでしょう:
#divclass(blockquote_ng){{
node && node.kids && node.kids[index] && foo(node.kids[index]);
}}
*** &aname(iterating_over_node_lists,option=nolink){ノードリストへの反復処理}
多くの場合ノードリストはフィルタ付きのイテレータとして実装されています。これは、&spanclass(keywd){length}のようなプロパティを参照するときのオーダーが O(n) であり、反復処理中に&spanclass(keywd){length}を再計算し続けると、そのオーダーは O(n^2) となるということを意味しています。
#divclass(blockquote_ng){{
var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i < paragraphs.length; i++) {
 (2)doSomething(paragraphs[i]);
}
}}
上のコードはこう書き換えたほうが優れています:
#blockquote(){{var paragraphs = document.getElementsByTagName('p');
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
 (2)doSomething(paragraph);
}
}}
要素が論理値のfalseとして評価される値を持たなければ、上のコードは全てのコレクションや配列で正常に動作します。
あるノードの子ノードに対して反復処理を行う際には、&spanclass(keywd){firstChild}プロパティと&spanclass(keywd){nextSibling}プロパティを使うこともできます:
#blockquote(){{var parentNode = document.getElementById('foo');
for (var child = parentNode.firstChild; child; child = child.nextSibling) {
 (2)doSomething(child);
}
}}
}}}}
}}}}}
----
2015-02-17T14:00:48+09:00
1424149248
-
JavaScriptの言語仕様に関するルール
https://w.atwiki.jp/aias-jsstyleguide2/pages/13.html
#include_js(http://cdn38.atwikiimg.com/aias-jsstyleguide2/?cmd=upload&act=open&page=%E3%83%88%E3%83%83%E3%83%97%E3%83%9A%E3%83%BC%E3%82%B8&file=goog_style_guide.js)
#divclass(page_title){
&this_page()
}
- 各項目の左側にある三角ボタン&html(<img src="http://www38.atwiki.jp/aias-jsstyleguide2/?cmd=upload&act=open&page=%E3%83%88%E3%83%83%E3%83%97%E3%83%9A%E3%83%BC%E3%82%B8&file=tri_down.gif" />)で、詳細情報の表示・非表示を切り替えられます。また下のボタンを使うと全項目を一度に変更することができます。
#divid(showhide_all){
&html(<div id="showhide_all_btn" class="show_dtl" ></div>)全て切り替える}
** &aname(var,option=nolink){var}
&html(<div id="shbtn_var" class="show_dtl" ></div>)常に、&spanclass(keywd){var}と共に変数を宣言します。
#divid(dtl_var){{{
#divclass(dtl){{
&spanclass(keywd2){var}の指定がない場合、変数はグローバルコンテキストに置かれ、既存の値を上書きする可能性があります。またもし宣言そのものがなければ、その変数のスコープがどこにあるのか分かりにくくなります(その変数はローカルスコープと同じように、DocumentやWindowの中に存在していてもよいのです)。従って常に&spanclass(keywd){var}と共に変数を宣言してください。
}}
}}}
** &aname(constants,option=nolink){定数}
&html(<div id="shbtn_constants" class="show_dtl" ></div>)
#divclass(indent){
- 定数値には&spanclass(keywd){NAMES_LIKE_THIS}のような名前をつけます。
- 変数やプロパティの参照先が固定されている(上書きできない)ことを示すには、&spanclass(keywd){@const}を使います。
- Internet Explorerがサポートしない&blanklink(const キーワード){https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/const}は決して使いません。
}
#divid(dtl_constants){{{{{
#divclass(dtl){{{{
#divclass(subcaption){定数値}
ある値を一定で変化しないものとして扱いたい場合、名前を&spanclass(keywd){CONSTANT_VALUE_CASE.ALL_CAPS}のように全て大文字にし、さらに&spanclass(keywd){@const}によって上書きできないことを示してください。
プリミティブ型(&spanclass(keywd){number}、&spanclass(keywd){string}、&spanclass(keywd){boolean})はもともと定数値です。
オブジェクトの不変性の判断は、より主観的です - 観察可能な状態変化が起きていない場合のみ、オブジェクトは不変とみなされるべきです。ただしCompilerはこの考え方を強制しません。
#divclass(subcaption){(変数・プロパティへの)定数ポインタ}
変数やプロパティに付けられた&spanclass(keywd){@const}アノテーションは、それらを上書きできないことを表します。この規則はCompilerによるビルド時に強制されます。またこの動作は&blanklink(const キーワード){https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/const}とも矛盾しません。(Internet Explorerがサポートしないため、&spanclass(keywd){const}キーワードは使いませんが。)
メソッドに付けられた&spanclass(keywd){@const}アノテーションは、サブクラスがそのメソッドをオーバーライドできないことを表します。
コンストラクタに付けられた&spanclass(keywd){@const}アノテーションは、そのクラスをサブクラス化できないことを表します。(Javaにおける&spanclass(keywd){@final}と同じです)
#divclass(subcaption){例}
&spanclass(keywd2){@const}は、(&spanclass(keywd){CONSTANT_VALUES_CASE}形式の名前のように)変数の値そのものが一定であることを必ずしも意味しません。一方&spanclass(keywd){CONSTANT_VALUES_CASE}形式の名前は&spanclass(keywd){@const}の示す内容を内包しています。
#blockquote(){{{#divclass(comment){{/**
 (1)* ミリ秒単位のリクエストタイムアウト時間
 (1)* &spanclass(doctag){@type} {number}
 (1)*/
}}
goog.example.TIMEOUT_IN_MILLISECONDS = 60;
}}}
大文字だけの名前は&spanclass(keywd){@const}の内容を含むため、この秒数は定数です。値の上書きはできません。
オープンソースのコンパイラは&spanclass(keywd){@const}がついていないシンボルの上書きを許容すると思われます。
#blockquote(){{{#divclass(comment){{/**
 (1)* 文字列を返すURLのマップ
 (1)* &spanclass(doctag){@const}
 (1)*/
}}
MyClass.fetchedUrlCache_ = new goog.structs.Map();
}}}
#blockquote(){{{#divclass(comment){{/**
 (1)* サブクラス化できないクラス
 (1)* &spanclass(doctag){@const}
 (1)* &spanclass(doctag){@constructor}
 (1)*/
}}
sloth.MyFinalClass = function() {};
}}}
このケースではプロパティ値であるオブジェクトは上書きされませんが、オブジェクトの値は頻繁に変化し一定ではありません。(このため名前には大文字ではなくキャメルケースが使われています)
}}}}
}}}}}
** &aname(semicolons,option=nolink){セミコロン}
&html(<div id="shbtn_semicolons" class="show_dtl" ></div>)常にセミコロンを使います。
#divid(dtl_semicolons){{{{{
#divclass(dtl){{{{
暗黙的なセミコロンの挿入に依存することは、微妙な、デバッグしにくい問題を引き起こします。もっと良い方法を選びましょう。
次のコードのセミコロンの無い箇所は、その危険性を示す典型的な例です:
#divclass(blockquote_ng){{{
&spanclass(comment){// 1.}
MyClass.prototype.myMethod = function() {
 (2)return 42;
} &spanclass(comment){// ここにはセミコロンがありません。}
(function() {
 (2)&spanclass(comment){// ローカルスコープを生成する関数の中に書かれた初期化処理。}
})();
var x = {
 (2)'i': 1,
 (2)'j': 2
} &spanclass(comment){// ここにはセミコロンがありません。}
&spanclass(comment){// 2. Internet ExplorerかFirefoxかによって処理を振り分けます。}
&spanclass(comment){// こんなコードは書かないとは思いますが、とりあえずお許しを。}
[ffVersion, ieVersion][isIE]();
var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] &spanclass(comment){// ここにはセミコロンがありません。}
&spanclass(comment){// 3. bash風の条件分岐。}
&nolink()-1 == resultOfOperation() || die();
}}}
#divclass(subcaption){何が起きるか?}
+ JavaScriptエラー - 先ず、42を返す関数が2番目の関数を引数として実行されます。次に42が "コール" され、数字なのでエラーが発生します。
+ &spanclass(keywd2){x[ffVersion, ieVersion][isIE]()}を実行しようとしたランタイムから、おそらく 'undefined にはそのようなプロパティはありません' という風なエラーが返されます。
+ 配列マイナス1は&spanclass(keywd){NaN}となり、&spanclass(keywd){NaN}はどんな値とも一致しないため必ず&spanclass(keywd){die()}が呼び出されます(たとえ&spanclass(keywd){resultOfOperation()}の戻り値が&spanclass(keywd){NaN}だったとしても)。&spanclass(keywd){THINGS_TO_EAT}には&spanclass(keywd){die()}の戻り値が代入されます。
#divclass(subcaption){なぜ?}
その存在が安全に推測される場合を除き、JavaScriptは文(statement)の末尾にセミコロンを要求します。上の各例では、関数宣言、オブジェクト、配列リテラルは1つの文の内側にいると見なされています。閉じ括弧は文の終了を表すには不十分です。JavaScriptは中置演算子(+、-など)や括弧では決して文を終了させません。
このことは本当に人々を驚かせます。従って文の末尾は確実にセミコロンで終わらせるべきです。
#divclass(subcaption){セミコロンと関数について}
関数式の後ろにはセミコロンを付けますが、関数宣言の後ろには付けません。その違いを示す非常に分かりやすい例がこれです:
#blockquote(){{{var foo = function() {
 (2)return true;
}; &spanclass(comment){// ここにはセミコロンを付けます}
function foo() {
 (2)return true;
} &spanclass(comment){// ここにはセミコロンを付けません}
}}}
}}}}
}}}}}
** &aname(nested_functions,option=nolink){ネストされた関数}
&html(<div id="shbtn_nested_functions" class="show_dtl" ></div>)使えます。
#divid(dtl_nested_functions){{
#divclass(dtl){
ネストされた関数は、例えば継続(continuation)の生成やヘルパー関数の隠蔽を行う際に、とても役立ちます。遠慮なく使いましょう。
}
}}
** &aname(function_declarations_within_blocks,option=nolink){ブロック内での関数宣言}
&html(<div id="shbtn_function_declarations_within_blocks" class="show_dtl" ></div>)使わないでください。
#divid(dtl_function_declarations_within_blocks){{{{
#divclass(dtl){{{
次のように書いてはいけません:
#divclass(blockquote_ng){{
if (x) {
 (2)function foo() {}
}
}}
ほとんどのスクリプトエンジンはブロック内での関数宣言をサポートしていますが、それはECMAScript(&blanklink(ECMA-262){http://www.ecma-international.org/publications/standards/Ecma-262.htm},13及び14項を参照)の仕様には含まれていません。各エンジンの実装は、互いの間でも将来のECMAScriptに対しても、一貫性が保証されていません。ECMAScriptは関数の宣言をスクリプトのトップレベルか関数内のスコープでのみ許しています。代わりに変数へ関数を代入すれば、ブロック内でも関数を定義することが可能です:
#blockquote(){{if (x) {
 (2)var foo = function() {};
}
}}
}}}
}}}}
** &aname(exceptions,option=nolink){例外}
&html(<div id="shbtn_exceptions" class="show_dtl" ></div>)使えます。
#divid(dtl_exceptions){{
#divclass(dtl){
もし自明でない何かを行うのであれば(アプリケーション開発フレームワークの利用など)、基本的に例外は避けられません。使いましょう。
}
}}
** &aname(custom_exceptions,option=nolink){独自の例外}
&html(<div id="shbtn_custom_exceptions" class="show_dtl" ></div>)使えます。
#divid(dtl_custom_exceptions){{
#divclass(dtl){
独自の例外を使わない場合、何かの値を返す関数が更にエラー情報も返そうとすると、その方法はトリッキーかつエレガントでないものになりそうです。戻り値をエラー情報への参照にするか、あるいはエラー情報をメンバに持つオブジェクトに変えることになるでしょう。これらは本質的に、原始的な例外ハンドリングのハックと言えます。必要であればどんどん独自の例外を使ってください。
}
}}
** &aname(standards_features,option=nolink){標準機能}
&html(<div id="shbtn_standards_features" class="show_dtl" ></div>)標準機能は非標準の機能よりも常に優先されます。
#divid(dtl_standards_features){{{
#divclass(dtl){{
移植性と互換性を最大化するため、常に標準化された機能の方を選択してください。(例えば&spanclass(keywd){string[3]}ではなく &spanclass(keywd){string.charAt(3)}を、DOM要素へのアクセスには特定のアプリケーションが提供する簡略化された機能ではなく、DOMの標準機能を使います)
}}
}}}
** &aname(wrapper_objects_for_primitive_types,option=nolink){プリミティブ型のラッパーオブジェクト}
&html(<div id="shbtn_wrapper_objects_for_primitive_types" class="show_dtl" ></div>)使わないでください。
#divid(dtl_wrapper_objects_for_primitive_types){{{{
#divclass(dtl){{{
プリミティブ型のラッパーオブジェクトは使う理由がないだけでなく、危険ですらあります:
#divclass(blockquote_ng){{
var x = new Boolean(false);
if (x) {
 (2)alert('hi'); &spanclass(comment){// 'hi'と表示されます。}
}
}}
このようにしてはいけません!
ただし、型のキャストに使うのは全く問題ありません:
#blockquote(){{var x = Boolean(0);
if (x) {
 (2)alert('hi'); &spanclass(comment){// これは決してアラートされません。}
}
typeof Boolean(0) == 'boolean';
typeof new Boolean(0) == 'object';
}}
これは何らかのデータを数値、文字列、論理値に変換するにはとても良い方法です。
}}}
}}}}
** &aname(multi_level_prototype_hierarchies,option=nolink){多段階のプロトタイプ階層}
&html(<div id="shbtn_multi_level_prototype_hierarchies" class="show_dtl" ></div>)好ましくありません。
#divid(dtl_multi_level_prototype_hierarchies){{{{
#divclass(dtl){{{
多段階のプロトタイプ階層はJavaScriptが実装する継承手法です。ユーザ定義クラス D のプロトタイプを別のユーザ定義クラス B にすると多段階の階層構造が作れます。しかしこれらの階層構造を正しく把握しておくのは、最初の状態と比べるとかなり難しいことです。
このため、継承には&blanklink(Closure Library){http://code.google.com/closure/library/}の&spanclass(keywd){goog.inherits()}のようなライブラリ関数を使うのが最善です。
#blockquote(){{function D() {
 (2)goog.base(this)
}
goog.inherits(D, B);
D.prototype.method = function() {
 (2)...
};
}}
}}}
}}}}
** &aname(method_and_property_definitions,option=nolink){メソッドとプロパティの定義}
#html2(){{
<div id="shbtn_method_and_property_definitions" class="show_dtl" ></div><span class="keywd2" >/** @constructor */ function SomeConstructor() { this.someProperty = 1; } Foo.prototype.someMethod = function() { ... };</span>
}}
#divid(dtl_method_and_property_definitions){{{{
#divclass(dtl){{{
"new"によって生成されるオブジェクトにメソッドやプロパティを付け加えるにはいくつかの方法がありますが、メソッドではこのスタイルが推奨されます:
#blockquote(){{Foo.prototype.bar = function() {
 (2)&spanclass(comment){/* ... */}
};
}}
その他のプロパティでは、コンストラクタの中で初期化を行うスタイルが推奨されます:
#blockquote(){{&spanclass(comment){/** @constructor */}
function Foo() {
 (2)this.bar = value;
}
}}
#divclass(subcaption){なぜ?}
現在のJavaScriptエンジンは、オブジェクトをその「形状」に基いて最適化します。&blanklink(プロパティの追加(プロトタイプに設定された値のオーバーライドも含まれます)はオブジェクトの形状を変化させ、パフォーマンスの低下をもたらします。){https://developers.google.com/v8/design#prop_access}
}}}
}}}}
** &aname(delete,option=nolink){delete}
&html(<div id="shbtn_delete" class="show_dtl" ></div>)より好ましいのは &spanclass(keywd){this.foo = null} の方です。
#divid(dtl_delete){{{{{
#divclass(dtl){{{{
#divclass(blockquote_ng){{{
Foo.prototype.dispose = function() {
 (2)delete this.property_;
};
}}}
ではなく、こう書きましょう:
#blockquote(){{{Foo.prototype.dispose = function() {
 (2)this.property_ = null;
};
}}}
現代のJavaScriptエンジンにおいて、プロパティの数を増減させる処理は、値の再割り当てに比べはるかに低速です。次の場合を除き、&spanclass(keywd){delete}キーワードは避けるべきです。
- プロパティ名をキーとする反復処理を行なっており、そのキーを削除する必要があるとき
- &spanclass(keywd2){if (key in obj)}の結果を変更する必要があるとき
}}}}
}}}}}
** &aname(closures,option=nolink){クロージャ}
&html(<div id="shbtn_closures" class="show_dtl" ></div>)使えます、しかし慎重に。
#divid(dtl_closures){{{{{
#divclass(dtl){{{{
クロージャを作成できる能力は、おそらく最も役に立つ、しかししばしば見落とされているJSの特長です。クロージャの動作についての良い解説は&blanklink(こちら){http://jibbering.com/faq/faq_notes/closures.html}をご覧ください。
しかし1つ覚えておいて欲しいのは、クロージャは自身を取り囲むスコープへのポインタを保持しているという点です。このためクロージャをDOM要素ヘ結びつけると、循環参照が発生しメモリリークとなることがあります。例えば次のコードです:
#divclass(blockquote_ng){{{
function foo(element, a, b) {
#html2{{
element.onclick = function() { <span class="comment" >/* a と b を使う */</span> };
}}
}
}}}
クロージャ関数は &spanclass(keywd){element}、&spanclass(keywd){a}、&spanclass(keywd){b}への参照を持っています。&spanclass(keywd){element}を使わないとしてもです。&spanclass(keywd){element}もまたクロージャへの参照を保持しており、そこでガーベジコレクションが回収できない循環ができてしまっています。この状況では、コードは次のように構成されるべきです:
#blockquote(){{{function foo(element, a, b) {
 (2)element.onclick = bar(a, b);
}
function bar(a, b) {
#html2{{
return function() { <span class="comment" >/* a と b を使う */</span> };
}}
}
}}}
}}}}
}}}}}
&aname(eval,option=nolink){}
**eval()
&html(<div id="shbtn_eval" class="show_dtl" ></div>)コードローダまたはREPL(Read-eval-print loop)にのみ使います。
#divid(dtl_eval){{{{{
#divclass(dtl){{{{
&spanclass(keywd2){eval()}はセマンティクスに混乱を引き起こします。またユーザの入力を含む文字列を&spanclass(keywd){eval()}することは危険な行為です。たいていはもっと適切、明確、安全なコードの書き方が存在するため、通常その利用は許容されません。
JSONを用いたRPCの際、データの解釈には&spanclass(keywd){eval()}の代わりに&spanclass(keywd){JSON.parse()}を使います。
以下のような結果を返すサーバがあるとします:
#blockquote(){{{
 (2)"name": "Alice",
 (2)"id": 31502,
 (2)"email": "looking_glass@example.com"
}
}}
#divclass(blockquote_ng){{
var userInfo = eval(feed);
var email = userInfo['email'];
}}
配信データが悪意あるJavaScriptコードを含むものに改変されていたとして、&spanclass(keywd){eval()}を使っていたらコードはそのまま実行されてしまうでしょう。
#blockquote(){{var userInfo = JSON.parse(feed);
var email = userInfo['email'];
}}
&spanclass(keywd2){JSON.parse()}を使うと、(全ての実行可能なJavaScriptを含む)不正なJSONに対して例外が発生します。
}}}}
}}}}}
&aname(with,option=nolink){}
**with() {}
&html(<div id="shbtn_with" class="show_dtl" ></div>)使わないでください。
#divid(dtl_with){{{{
#divclass(dtl){{{
&spanclass(keywd2){with}の使用はプログラムのセマンティクスを曇らせます。&spanclass(keywd){with}で指定されたオブジェクトはローカル変数と衝突するようなプロパティを持てるため、プログラムの意図が大きく変えられてしまうおそれがあります。例えばこのコードでは何が起きるでしょうか?
#divclass(blockquote_ng){{
with (foo) {
 (2)var x = 3;
 (2)return x;
}
}}
答えは「あらゆることが起きる」です。ローカル変数&spanclass(keywd){x}は&spanclass(keywd){foo}のプロパティに乗っ取られます。もし&spanclass(keywd){x}がsetterだった場合、&spanclass(keywd){3}の代入は他の多くのコードを実行させる原因となりえます。&spanclass(keywd){with}を使ってはいけません。
}}}
}}}}
** &aname(this,option=nolink){this}
&html(<div id="shbtn_this" class="show_dtl" ></div>)オブジェクトのコンストラクタとメソッド、クロージャの作成時にのみ使います。
#divid(dtl_this){{{
#divclass(dtl){{
&spanclass(keywd2){this}のセマンティクスは扱いが難しく、場合によってその参照先はグローバルオブジェクト(ほとんどはこれです)、呼び出し元のスコープ(&spanclass(keywd){eval}内)、DOMツリー内のノード(要素に追加されたHTMLイベントハンドラ内)、新しく生成されたオブジェクト(コンストラクタ内)、何か他のオブジェクト(&spanclass(keywd){call()}または&spanclass(keywd){apply()}された関数内)と変化します。
&spanclass(keywd2){this}は容易に間違いの原因になってしまうので、本当に必要な次の場面だけに使用を限定します。
- コンストラクタの中
- オブジェクトのメソッドの中(クロージャの作成時を含む)
}}
}}}
**&aname(for_in_loop,option=nolink){for-in ループ}
&html(<div id="shbtn_for_in_loop" class="show_dtl" ></div>)オブジェクト / マップ / ハッシュ内をキーによって走査する場合のみ使えます。
#divid(dtl_for_in_loop){{{{
#divclass(dtl){{{
&spanclass(keywd2){for-in}ループはしばしば 配列(&spanclass(keywd){Array})内の要素をループ処理するという、間違った使い方をされています。&spanclass(keywd){for-in}ループは &spanclass(keywd){0}から&spanclass(keywd){length-1}までをループするのではなく、オブジェクトとそのプロトタイプチェーンに存在するキーを走査するものです。従ってそのような使い方はエラーを起こしがちです。失敗例をいくつか示します:
#divclass(blockquote_ng){{
function printArray(arr) {
 (2)for (var key in arr) {
 (4)print(arr[key]);
 (2)}
}
printArray([0,1,2,3]); &spanclass(comment){// これは動作します。}
var a = new Array(10);
printArray(a); &spanclass(comment){// これは正しくありません。}
a = document.getElementsByTagName('*');
printArray(a); &spanclass(comment){// これは正しくありません。}
a = [0,1,2,3];
a.buhu = 'wine';
printArray(a); &spanclass(comment){// これも正しくありません。}
a = new Array;
a[3] = 3;
printArray(a); &spanclass(comment){// これも正しくありません。}
}}
配列のループには必ず通常の&spanclass(keywd){for}文を使ってください。
#blockquote(){{function printArray(arr) {
 (2)var l = arr.length;
 (2)for (var i = 0; i < l; i++) {
 (4)print(arr[i]);
 (2)}
}
}}
}}}
}}}}
** &aname(associative_arrays,option=nolink){連想配列}
&html(<div id="shbtn_associative_arrays" class="show_dtl" ></div>)決して&spanclass(keywd){Array}をマップ / ハッシュ / 連想配列として使わないでください。
#divid(dtl_associative_arrays){{{{
#divclass(dtl){{{
&spanclass(keywd2){Array}を連想配列として使うことは許されていません..もっと正確に言えば、数字インデックス以外で配列要素にアクセスすることは許されていません。もしマップやハッシュが必要なのであれば、&spanclass(keywd){Array}の代わりに&spanclass(keywd){Object}を使いましょう。実際、連想配列に求められている機能は&spanclass(keywd){Array}ではなく&spanclass(keywd){Object}に実装されており、&spanclass(keywd){Array}はただ&spanclass(keywd){Object}を拡張しているに過ぎません(その他のJSの全てのオブジェクト、つまり &spanclass(keywd){Date}、&spanclass(keywd){RegExp}、&spanclass(keywd){String}なども同様です)。
}}}
}}}}
** &aname(multiline_string_literals,option=nolink){複数行の文字列リテラル}
&html(<div id="shbtn_multiline_string_literals" class="show_dtl" ></div>)使わないでください。
#divid(dtl_multiline_string_literals){{{{
#divclass(dtl){{{
このような書き方は禁止です:
#divclass(blockquote_ng){{
var myString = 'A rather long string of English text, an error message \
 (16)actually that just keeps going and going -- an error \
 (16)message to make the Energizer bunny blush (right through \
 (16)those Schwarzenegger shades)! Where was I? Oh yes, \
 (16)you\'ve got an error and all the extraneous whitespace is \
 (16)just gravy. Have a nice day.';
}}
各行の先頭にある空白はコンパイル時にも安全に取り除かれることはなく、バックスラッシュ(\)の後ろの空白は分かりにくいエラーをもたらします。またこの記法はほとんどのエンジンでサポートされているとはいえ、ECMAScriptの標準ではありません。
代わりに、文字列の結合を使ってください:
#blockquote(){{var myString = 'A rather long string of English text, an error message ' +
 (4)'actually that just keeps going and going -- an error ' +
 (4)'message to make the Energizer bunny blush (right through ' +
 (4)'those Schwarzenegger shades)! Where was I? Oh yes, ' +
 (4)'you\'ve got an error and all the extraneous whitespace is ' +
 (4)'just gravy. Have a nice day.';
}}
}}}
}}}}
** &aname(array_and_object_literals,option=nolink){配列リテラルとオブジェクトリテラル}
&html(<div id="shbtn_array_and_object_literals" class="show_dtl" ></div>)使えます。
#divid(dtl_array_and_object_literals){{{{
#divclass(dtl){{{
&spanclass(keywd2){Array}と&spanclass(keywd){Object}のコンストラクタではなく、配列リテラルとオブジェクトリテラルを使って下さい。
&spanclass(keywd2){Array}コンストラクタの引数はエラーの原因になりがちです:
#divclass(blockquote_ng){{
&spanclass(comment){// 配列の長さは3。}
var a1 = new Array(x1, x2, x3);
&spanclass(comment){// 配列の長さは2。}
var a2 = new Array(x1, x2);
&spanclass(comment){// もし x1 が自然数であれば、配列の長さは x1 になります。}
&spanclass(comment){// もし x1 が数値でかつ自然数でなければ、例外が発生します。}
&spanclass(comment){// それ以外なら、配列は x1 を値とする長さ1の配列になります。}
var a3 = new Array(x1);
&spanclass(comment){// 配列の長さは0。}
var a4 = new Array();
}}
このため、誰かが引数の数を2つから1つに変更すると、その配列の長さは想定と合わなくなる可能性があります。
これらの奇妙な事例は、より可読性の高い配列リテラルを使用することで避けられます:
#blockquote(){{var a = [x1, x2, x3];
var a2 = [x1, x2];
var a3 = [x1];
var a4 = [];
}}
&spanclass(keywd2){Object}コストラクタには同じ問題はありませんが、可読性と一貫性の面からオブジェクトリテラルを使うべきです:
#divclass(blockquote_ng){{
var o = new Object();
var o2 = new Object();
o2.a = 0;
o2.b = 1;
o2.c = 2;
o2['strange key'] = 3;
}}
上は、こう書かれるべきです:
#blockquote(){{var o = {};
var o2 = {
 (2)a: 0,
 (2)b: 1,
 (2)c: 2,
 (2)'strange key': 3
};
}}
}}}
}}}}
** &aname(modifying_prototypes_of_builtin_objects,option=nolink){組込みオブジェクトのプロトタイプの書き換え}
&html(<div id="shbtn_modifying_prototypes_of_builtin_objects" class="show_dtl" ></div>)しないでください。
#divid(dtl_modifying_prototypes_of_builtin_objects){{{
#divclass(dtl){{
&spanclass(keywd2){Object.prototype}や&spanclass(keywd){Array.prototype}のような組込みオブジェクトのプロトタイプを書き換えることは、固く禁じます。同じ組込みであっても&spanclass(keywd){Function.prototype}などはそれほど危険ではありませんが、それでもデバッグの難しい問題を引き起こす可能性があります。よって書き換えは避けるべきです。
}}
}}}
** &aname(ies_conditional_comments,option=nolink){Internet Explorerの条件付きコメント}
&html(<div id="shbtn_ies_conditional_comments" class="show_dtl" ></div>)使わないでください。
#divid(dtl_ies_conditional_comments){{{{
#divclass(dtl){{{
これは禁止です:
#divclass(blockquote_ng){{
var f = function () {
#html2(){{
<span class="comment" >/*@cc_on if (@_jscript) { return 2* @*/ 3; /*@ } @*/</span>
}}
};
}}
条件付きコメントはライタイムのJavaScriptシンタックス・ツリーを改変してしまうので、ツールによる自動化の妨げになります。
}}}
}}}}
----
2015-02-17T13:34:02+09:00
1424147642
-
トップページ
https://w.atwiki.jp/aias-jsstyleguide2/pages/1.html
-このサイトは &blanklink(Google JavaScript Style Guide){http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml}(Revision 2.93) を私的に日本語訳したものです。
-この翻訳の内容について、翻訳者は一切の責任を負いません。ご利用は自己責任でお願いします。
-以下のコーディングルールは、最終的にコードを&blanklink(Closure Compiler){http://code.google.com/p/closure-compiler/}にかけて完成させることが暗黙の前提となっている点に注意してください。Closure CompilerはGoogle自身が提供しているJavaScript圧縮・最適化ツールです。(こちらの&blanklink(日本語の解説){http://www37.atwiki.jp/aias-closurecompiler/}も参考にしてみてください。)
-JavaScriptコードがこのスタイルガイドに適合しているかどうかを検証する、&blanklink(Clisure Linter){http://code.google.com/intl/ja/closure/utilities/index.html}というツールがGoogleから提供されています。使い方は&link(こちら){Closure Linterの使い方}を参照してください。
#divclass(author){{
2.93 版
Aaron Whyte
Bob Jervis
Dan Pupius
Erik Arvidsson
Fritz Schneider
Robby Walker
}}
** 目次
#divclass(content_lite){{
- &link2(JavaScriptの言語仕様に関するルール)
#divclass(content_lite_list){
|&link_anchor(var,pageid=13){var}|&link_anchor(constants,pageid=13){定数}|&link_anchor(semicolons,pageid=13){セミコロン}|&link_anchor(nested_functions,pageid=13){ネストされた関数}|
|&link_anchor(function_declarations_within_blocks,pageid=13){ブロック内での関数宣言}|&link_anchor(exceptions,pageid=13){例外}|&link_anchor(custom_exceptions,pageid=13){独自の例外}|&link_anchor(standards_features,pageid=13){標準機能}|
|&link_anchor(wrapper_objects_for_primitive_types,pageid=13){プリミティブ型のラッパーオブジェクト}|&link_anchor(multi_level_prototype_hierarchies,pageid=13){多段階のプロトタイプ階層}|&link_anchor(method_and_property_definitions,pageid=13){メソッドとプロパティの定義}|&link_anchor(delete,pageid=13){delete}|
|&link_anchor(closures,pageid=13){クロージャ}|&link_anchor(eval,pageid=13){eval()}|&link_anchor(with,pageid=13){with()}|&link_anchor(this,pageid=13){this}|
|&link_anchor(for_in_loop,pageid=13){for-in ループ}|&link_anchor(associative_arrays,pageid=13){連想配列}|&link_anchor(multiline_string_literals,pageid=13){複数行の文字列リテラル}|&link_anchor(array_and_object_literals,pageid=13){配列リテラルとオブジェクトリテラル}|
|&link_anchor(modifying_prototypes_of_builtin_objects,pageid=13){組込みオブジェクトのプロトタイプの書き換え}|&link_anchor(ies_conditional_comments,pageid=13){Internet Explorerの条件付きコメント}||||
}
- &link2(JavaScriptのスタイルに関するルール)
#divclass(content_lite_list){
|&link_anchor(naming,pageid=15){命名規則}|&link_anchor(custom_tostring_methods,pageid=15){独自のtoString()メソッド}|&link_anchor(deferred_initialization,pageid=15){変数初期化の遅延}|&link_anchor(explicit_scope,pageid=15){明示的なスコープ}|
|&link_anchor(code_formatting,pageid=15){コードのフォーマット}|&link_anchor(parentheses,pageid=15){丸括弧}|&link_anchor(strings,pageid=15){文字列}|&link_anchor(visibility,pageid=15){可視性(privateまたはprotectedなフィールド)}|
|&link_anchor(js_types,pageid=15){JavaScriptのデータ型}|&link_anchor(comments,pageid=15){コメント}|&link_anchor(providing_dependencies_with_goog_provide,pageid=15){goog.provideによる依存関係の規定}|&link_anchor(compiling,pageid=15){コンパイル}|
|&link_anchor(tips_and_tricks,pageid=15){ヒントとテクニック}||||
}
}}
** はじめに
JavaScriptはGoogleの多くのオープンソースプロジェクトで、主要なクライアントサイドのスクリプト言語として使用されています。このスタイルガイドはJavaScriptプログラムのための''すべきこと''と''すべきでないこと''のリストです。
#divclass(toppage_summary){{{
** &link2(JavaScriptの言語仕様に関するルール)
#divclass(negative_space)
*** &link_anchor(var,pageid=13){var}
常に、&spanclass(keywd){var}と共に変数を宣言します。
*** &link_anchor(constants,pageid=13){定数}
- 定数値には&spanclass(keywd){NAMES_LIKE_THIS}のような名前をつけます。
- 変数やプロパティの参照先が固定されている(上書きできない)ことを示すには&spanclass(keywd){@const}を使います。
- Internet Explorerがサポートしない&blanklink(const キーワード){https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/const}は決して使いません。
*** &link_anchor(semicolons,pageid=13){セミコロン}
常にセミコロンを使います。
*** &link_anchor(nested_functions,pageid=13){ネストされた関数}
使えます。
*** &link_anchor(function_declarations_within_blocks,pageid=13){ブロック内での関数宣言}
使わないでください。
*** &link_anchor(exceptions,pageid=13){例外}
使えます。
*** &link_anchor(custom_exceptions,pageid=13){独自の例外}
使えます。
*** &link_anchor(standards_features,pageid=13){標準機能}
標準機能は非標準の機能よりも常に優先されます。
*** &link_anchor(wrapper_objects_for_primitive_types,pageid=13){プリミティブ型のラッパーオブジェクト}
使わないでください。
*** &link_anchor(multi_level_prototype_hierarchies,pageid=13){多段階のプロトタイプ階層}
好ましくありません。
*** &link_anchor(method_and_property_definitions,pageid=13){メソッドとプロパティの定義}
#html2(){{
<span class="keywd2" >/** @constructor */ function SomeConstructor() { this.someProperty = 1; } Foo.prototype.someMethod = function() { ... };</span>
}}
*** &link_anchor(delete,pageid=13){delete}
より好ましいのは &spanclass(keywd){this.foo = null} の方です。
*** &link_anchor(closures,pageid=13){クロージャ}
使えます、しかし慎重に。
*** &link_anchor(eval,pageid=13){eval()}
コードローダまたはREPL(Read-eval-print loop)にのみ使います。
*** &link_anchor(with,pageid=13){with(){}}
使わないでください。
*** &link_anchor(this,pageid=13){this}
オブジェクトのコンストラクタとメソッド、クロージャの作成時にのみ使います。
*** &link_anchor(for_in_loop,pageid=13){for-in ループ}
オブジェクト / マップ / ハッシュ内をキーによって走査する場合のみ使えます。
*** &link_anchor(associative_arrays,pageid=13){連想配列}
決して &spanclass(keywd){Array} をマップ / ハッシュ / 連想配列として使わないでください。
*** &link_anchor(multiline_string_literals,pageid=13){複数行の文字列リテラル}
使わないでください。
*** &link_anchor(array_and_object_literals,pageid=13){配列リテラルとオブジェクトリテラル}
使えます。
*** &link_anchor(modifying_prototypes_of_builtin_objects,pageid=13){組込みオブジェクトのプロトタイプの書き換え}
しないでください。
*** &link_anchor(ies_conditional_comments,pageid=13){Internet Explorerの条件付きコメント}
使わないでください。
** &link2(JavaScriptのスタイルに関するルール)
#divclass(negative_space)
*** &link_anchor(naming,pageid=15){命名規則}
原則として、関数は&spanclass(keywd){functionNamesLikeThis}、変数は&spanclass(keywd){variableNamesLikeThis}、クラスは&spanclass(keywd){ClassNamesLikeThis}、列挙型は&spanclass(keywd){EnumNamesLikeThis}、メソッドは&spanclass(keywd){methodNamesLikeThis}、定数は&spanclass(keywd){CONSTANT_VALUES_LIKE_THIS}、名前空間は&spanclass(keywd){foo.namespaceNamesLikeThis.bar}、ファイルは&spanclass(keywd){filenameslikethis.js}のように、それぞれ命名してください。
*** &link_anchor(custom_tostring_methods,pageid=15){独自のtoString()メソッド}
副作用なしで常に成功すること。
*** &link_anchor(deferred_initialization,pageid=15){変数初期化の遅延}
OK。
*** &link_anchor(explicit_scope,pageid=15){明示的なスコープ}
常にそうしてください。
*** &link_anchor(code_formatting,pageid=15){コードのフォーマット}
詳しい情報を見るにはリンクをクリックしてください。
*** &link_anchor(parentheses,pageid=15){丸括弧}
必要なときだけ使います。
*** &link_anchor(strings,pageid=15){文字列}
&spanclass(keywd2){"}より&spanclass(keywd){'}を使います。
*** &link_anchor(visibility,pageid=15){可視性(privateまたはprotectedなフィールド)}
JSDocアノテーションの&spanclass(keywd){@private}と&spanclass(keywd){@protected}の利用を推奨します。
*** &link_anchor(js_types,pageid=15){JavaScriptのデータ型}
Compilerによる型の強制を推奨します。
*** &link_anchor(comments,pageid=15){コメント}
JSDocを使ってください。
*** &link_anchor(providing_dependencies_with_goog_provide,pageid=15){goog.provideによる依存関係の規定}
トップレベルのシンボルだけを規定します。
*** &link_anchor(compiling,pageid=15){コンパイル}
必須です。
*** &link_anchor(tips_and_tricks,pageid=15){ヒントとテクニック}
JavaScriptについてもう少しだけ。
}}}
** 最後に
#divclass(emph3){一貫性を持たせてください。}
コードを編集するとき、少しの間周辺のコードを眺めてからスタイルを決めるようにしてください。それらが全ての計算記号の前後にスペースを入れているのであれば、あなたもそうすべきです。もしコメントが#マークで四角く囲まれているなら、あなたもコメントを#マークで囲んでください。
スタイルガイドラインの意義は、人々がコーディングに関する共通の語彙を持つことにあります。そうすれば、どう話すかより何を話すかに集中できるようになります。我々が示したのは共通語彙としての全体的なスタイルルールですが、ローカルルールもまた同じように重要です。もしあなたがファイルに追加したコードが既存のコードとかけ離れていたら、他の人はコードを読むリズムを狂わされてしまいます。そうならないようにしてください。
----
2015-02-17T13:02:02+09:00
1424145722
-
JSDocコメント
https://w.atwiki.jp/aias-jsstyleguide2/pages/14.html
#divclass(page_title){
&this_page()
}
我々は&blanklink(C++ style for comments){http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Comments}の考え方に従います。
全てのファイル、クラス、メソッド、プロパティに&blanklink(JSDoc){http://code.google.com/p/jsdoc-toolkit/}コメントが、適切な&link_anchor(jsdoc_tag_reference){タグ}と&link_anchor(js_type_language,pageid=17){データ型}を伴って記されるべきです。また名前から明白に判断できる場合を除き、プロパティ、メソッド、メソッドの引数、メソッドの戻り値を説明する文章が含まれているべきです。
インラインのコメントには&spanclass(keywd){//}の方を使います。
完全文(Complete sentence)で書くことを推奨しますが、必須ではありません。完全文を使う場合は適切に大文字で開始し、句読点で終わらせましょう。
*** &anchor(comment_syntax,option=nolink){コメントの構文}
JSDocの構文は&blanklink(JavaDoc){http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html}を元にしています。沢山のツールがJSDocコメントから取り出したメタデータを使ってコードの検証や最適化を行なっているため、コメントは適切に整形されたものでなければなりません。
#blockquote(){{{#divclass(comment){{
/**
 (1)* JSDocコメントはスラッシュと2つのアスタリスクから始めます。
 (1)* インラインタグは &spanclass(doctag){{@code this}} のように波括弧で囲みます。
 (1)* &spanclass(doctag){@desc} ブロックタグは必ず行の先頭から開始します。
 (1)*/
}}
}}}
*** &anchor(jsdoc_indentation,option=nolink){JSDocのインデント}
ブロックタグ内で改行が必要な場合、コードの改行と同様にスペース4つ分インデントしてください。
#blockquote(){{{#divclass(comment){{/**
 (1)* 長いparam/returnアノテーションの説明文の折り返し方を示します。
 (1)* &spanclass(doctag){@param} {string} foo これは1行でおさめるには長すぎるパラメータの
 (1)* (5)説明文です。
 (1)* &spanclass(doctag){@return} {number} この戻り値の説明文は長すぎて、とても1行の中には
 (1)* (5)入りきりません。
 (1)*/
}}
project.MyClass.prototype.method = function(foo) {
 (2)return 5;
};
}}}
&spanclass(keywd2){@fileoverview}コマンドをインデントすべきではありません。&spanclass(keywd){@desc}コマンドはインデントしなくてかまいません。
推奨はしませんが、説明文の先頭で折り返しを揃える書き方も認めます。
#blockquote(){{{#divclass(comment){{/**
 (1)* これは決してお勧め'しない'インデントの方法です。
 (1)* &spanclass(doctag){@param} {string} foo これは1行でおさめるには長すぎるパラメータの
 (1)* (21)説明文です。
 (1)* &spanclass(doctag){@return} {number} この戻り値の説明文は長すぎて、とても1行の中には
 (1)* (18)入りきりません。
 (1)*/
}}
project.MyClass.prototype.method = function(foo) {
 (2)return 5;
};
}}}
*** &aname(html_in_jsdoc,option=nolink){JSDocの中のHTML}
JavaDocと同じく、JSDocも多くのHTMLタグをサポートしています。<code>、<pre>、<tt>、<strong>、<ul>、<ol>、<li>、<a> 等々です。
これは、プレインテキストに書式を設定しても無視されることを意味します。このため、スペースによってJSDocを整形しようとしてはいけません:
#divclass(blockquote_ng){{{
#divclass(comment){{/**
 (1)* 以下の3つの要因に基づいて重さを計算します:
 (1)* (3)送った項目
 (1)* (3)受け取った項目
 (1)* (3)タイムスタンプ
 (1)*/
}}
}}}
上のコメントは次のように表示されます。
以下の3つの要因に基づいて重さを計算します: 送った項目 受け取った項目 タイムスタンプ
代わりに、こうしてください:
#blockquote(){{{#divclass(comment){{/**
 (1)* 以下の3つの要因に基づいて重さを計算します:
 (1)* <ul>
 (1)* <li>送った項目
 (1)* <li>受け取った項目
 (1)* <li>タイムスタンプ
 (1)* </ul>
 (1)*/
}}
}}}
JSDocコメントを適切な形式で書くには、&blanklink(JavaDoc){http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html}のスタイルガイドが役に立ちます。
*** &anchor(top_file_level_comments,option=nolink){トップ(ファイル)レベルのコメント}
&blanklink(著作権表示){http://google-styleguide.googlecode.com/svn/trunk/copyright.html}と著作者情報は省略できます。ファイルが複数のクラス定義からなる場合には、一般的にファイル概要の記述が推奨されます。トップレベルのコメントは、そのファイルの中のコードに詳しくない読者をうまく導くように設計しましょう。そこにはファイルの全体的な説明、著者名、依存関係や互換性の情報が提供されているべきです。例を示します:
#blockquote(){{{#divclass(comment){{
/**
 (1)* &spanclass(doctag){@fileoverview} ファイルの説明、使い方や依存関係に
 (1)* ついての情報。
 (1)*/
}}
}}}
*** &anchor(class_comments,option=nolink){クラスへのコメント}
クラスへのコメントには、説明文と&link_anchor(constructor-tag,pageid=17){コンストラクタであることを示すタグ}を記述します。
#blockquote(){{{#divclass(comment){{/**
 (1)* 何だか楽しくなるクラス
 (1)* &spanclass(doctag){@param} {string} arg1 もっと面白くする引数
 (1)* &spanclass(doctag){@param} {Array.<number>} arg2 処理される数値のリスト
 (1)* &spanclass(doctag){@constructor}
 (1)* &spanclass(doctag){@extends} {goog.Disposable}
 (1)*/
}}
project.MyClass = function(arg1, arg2) {
 (1)&spanclass(comment){// ...}
};
goog.inherits(project.MyClass, goog.Disposable);
}}}
*** &anchor(method_and_function_comments,option=nolink){メソッドと関数へのコメント}
パラメータと戻り値について記述されるべきです。メソッドのパラメータと戻り値が自明である場合には、説明を省略してもかまいません。メソッドの説明文は三人称の平叙文で書きます。
#blockquote(){{{#divclass(comment){{
/**
 (1)* MyClass のインスタンスを操作し、何かを返します。
 (1)* &spanclass(doctag){@param} {project.MyClass} obj 折り返して2行にしなければならないほど
 (1)* (5)長いコメントが続く、MyClass のインスタンス
 (1)* &spanclass(doctag){@return} {boolean} 何かが起きたかどうか
 (1)*/
}}
function PR_someMethod(obj) {
 (1)&spanclass(comment){// ...}
}
}}}
*** &anchor(property_comments,option=nolink){プロパティへのコメント}
#blockquote(){{{#divclass(comment){{/** &spanclass(doctag){@constructor} */}}
project.MyClass = function() {
#divclass(comment){{ (2)/**
 (3)* 枠の中に入れられる最大数。
 (3)* &spanclass(doctag){@type} {number}
 (3)*/
}}
 (2)this.someProperty = 4;
}
}}}
*** &aname(jsdoc_tag_reference,option=nolink){JSDocタグリファレンス}
|タグ|書式と例|説明|h
|@author|&html(<div class="tt3" ><span class="keywd2" >@author メールアドレス (名 姓)</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * <span class="doctag" >@fileoverview</span> テキストエリアを扱うためのユーティリティ群。<br> * <span class="doctag" >@author</span> kuth@google.com (Uthur Pendragon)<br> */</div></div>)|ファイルの著者、またはテストの所有者を記載します。通常&spanclass(keywd){@fileoverview}を含むコメントの中でのみ使用されます。|
|@code|&html(<div class="tt3" ><span class="keywd2" >{@code ...}</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * 選択されたものの中で次の位置に移動します。<br> * Throws {<span class="doctag">@code</span> goog.iter.StopIteration} 最後尾を<br> * 超えた場合に発生する。<br> * <span class="doctag">@return</span> {Node} 次の位置のノード。<br> */</div>goog.dom.RangeIterator.prototype.next = function() {<br> <span class="comment">// ...</span><br>};</div>)|JSDocの説明文に含まれる語句がコードであることを示します。生成されたドキュメント内で適切に整形されることが想定されています。|
|@const|&html(<div class="tt3" ><span class="keywd2" >@const</span><br><span class="keywd2" >@const {型名}</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag">@const</span> */</div> var MY_BEER = 'stout';<br><br><div class="comment">/**<br> * 名前空間が好きなビールの種類<br> * <span class="doctag">@const</span> {string}<br> */</div>mynamespace.MY_BEER = 'stout';<br><br><span class="comment">/** <span class="doctag">@const</span> */</span> MyClass.MY_BEER = 'stout';<br><br><div class="comment">/**<br> * リクエストを初期化します。<br> * <span class="doctag">@const</span><br> */</div>mynamespace.Request.prototype.initialize = function() {<div class="comment" > // サブクラスはこのメソッドをオーバーライドできません。</div>};</div>)|変数(またはプロパティ)が読み取り専用であることを示します。このタグはインラインで記述するのに向いています。&br()&br()&spanclass(keywd2){@const}が付けられた変数はある値への固定された参照と見なされ、&spanclass(keywd){@const}付きの変数やプロパティが上書きされているとCompilerは警告を出力します。&br()&br()データ型を明確に推測できるのであれば型の宣言は省いてもかまいません。その他のコメントの追加も必須ではありません。&br()&br()メソッドに&spanclass(keywd2){@const}が付けられている場合、そのメソッドに対しては単に上書きだけでなく、サブクラスによるオーバーライドも禁止されていることを意味します。&br()&br()&spanclass(keywd2){@const}のより詳細な説明は「&link_anchor(constants,pageid=13){定数}」を参照してください。|
|@constructor|&html(<div class="tt3" ><span class="keywd2" >@constructor</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * 長方形。<br> * <span class="doctag">@constructor</span><br> */</div>function GM_Rect() {<br> ...<br>}</div>)|クラスの説明の中で使い、関数がコンストラクタであることを示します。|
|@define|&html(<div class="tt3" ><span class="keywd2" >@define {型名} 説明文</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag">@define</span> {boolean} */</div>var TR_FLAGS_ENABLE_DEBUG = true;<br><br><div class="comment">/**<br> * <span class="doctag">@define</span> {boolean} ブラウザがIEかどうかが<br> * コンパイル時に設定される。<br> */</div>goog.userAgent.ASSUME_IE = false;</div></div>)|コンパイル時にCompilerによって上書きされる定数であることを示します。左の例でコンパイルフラグに&spanclass(keywd){--define='goog.userAgent.ASSUME_IE=true'}と指定すると、ビルド後のファイルでは&spanclass(keywd){goog.userAgent.ASSUME_IE}の値はtrueに置き換えられます。|
|@deprecated|&html(<div class="tt3" ><span class="keywd2" >@deprecated 説明文</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * ノードがフィールドかどうかを判定します。<br> * <span class="doctag">@return</span> {boolean} 要素の内容が<br> * 編集可能ならtrue。ただし要素そのものは<br> * 編集不可。<br> * <span class="doctag">@deprecated</span> isField() を使ってください。<br> */</div>BN_EditUtil.isTopEditableField = function(node) {<br> <span class="comment">// ...</span><br>};</div>)|関数、メソッド、プロパティをこれ以上使うべきでないことを伝えます。説明文の中でそれに替わるものを指示するのが普通です。|
|@dict|&html(<div class="tt3" ><span class="keywd2" >@dict 説明文</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag">@constructor</span><br> * <span class="doctag">@dict</span><br> */</div>function Foo(x) {<br> this['x'] = x;<br>}<br>var obj = new Foo(123);<br>var num = obj.x; <span class="comment">// 警告</span><br><br>(<span class="comment">/**</span> <span class="doctag">@dict</span> <span class="comment">*/</span> { x: 1 }).x = 123; <span class="comment">// 警告</span></div>)|コンストラクタ(左の例の&spanclass(keywd){Foo})に&spanclass(keywd){@dict}が付けられた場合、&spanclass(keywd){Foo}オブジェクトのプロパティへのアクセスは角括弧による表記法でのみ可能となります。アノテーションをオブジェクトリテラルに直接記述することもできます。|
|@enum|&html(<div class="tt3" ><span class="keywd2" >@enum {型名}</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * 3つの状態を値にもつ列挙型。<br> * <span class="doctag">@enum</span> {number}<br> */</div>project.TriState = {<br> TRUE: 1,<br> FALSE: -1,<br> MAYBE: 0<br>};</div>)| |
|@export|&html(<div class="tt3" ><span class="keywd2" >@export</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag">@export</span> */</div>foo.MyPublicClass.prototype.myPublicMethod = function() {<div class="comment"> // ...</div>};</div>)|&spanclass(keywd2){--generate_exports}フラグを付けてコンパイルを実行すると、左のコードは次のように出力されます:&br()&br()&html(<div class="bq_m" >goog.exportSymbol('foo.MyPublicClass.prototype.myPublicMethod',<br> foo.MyPublicClass.prototype.myPublicMethod);</div>)&br()コンパイル前のシンボルがエクスポートされているのが分かります。&spanclass(keywd){@export}を使用するには以下の条件のどちらかを満たしていなければなりません。&br()&br()1. &spanclass(keywd){//javascript/closure/base.js}をインクルードしている&br()2. コードベース内に&spanclass(keywd){goog.exportSymbol}と&spanclass(keywd){goog.exportProperty}の両方が同じメソッドシグネチャで存在している。|
|@expose|&html(<div class="tt3" ><span class="keywd2" >@expose</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag">@export</span> */</div>MyClass.prototype.exposedProperty = 3;</div>)|外部公開されているプロパティであることを宣言します。外部公開されたプロパティには削除、名前の変更、圧縮、Compilerによるいかなる最適化も実施されなくなります。同じ名前のプロパティを個別に最適化することはできません。&br()&br()ライブラリのコードに対しては&spanclass(keywd){@expose}を使用すべきではありません。今まで正常に行われていたプロパティの削除を妨げることになるからです。|
|@extends|&html(<div class="tt3" ><span class="keywd2" >@extends 型名<br>@extends {型名}</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * 常に空のノードリスト<br> * <span class="doctag">@constructor</span><br> * <span class="doctag">@extends</span> goog.ds.BasicNodeList<br> */</div>goog.ds.EmptyNodeList = function() {<br> ...<br>};</div>)|&spanclass(keywd2){@constructor}と共に使用し、あるクラスが別のクラスを継承していることを示します。型を囲む波括弧は省略可能です。|
|@externs|&html(<div class="tt3" ><span class="keywd2" >@externs</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag" >@fileoverview</span> これはexternファイルです。<br> * <span class="doctag" >@externs</span><br> */</div><br>var document;</div>)|externファイルであることを宣言します。|
|@fileoverview|&html(<div class="tt3" ><span class="keywd2" >@fileoverview 説明文</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * <span class="doctag" >@fileoverview</span> 何かをするユーティリティ群。その説明には<br> * このように長くてインデントされていないコメントを必要とします。<br> * <span class="doctag" >@author</span> kuth@google.com (Uthur Pendragon)<br> */</div>)|ファイルレベルの情報を提供するコメントブロックを構成します。|
|@implements|&html(<div class="tt3" ><span class="keywd2" >@implements 型名<br>@implements {型名}</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * 形状。<br> * <span class="doctag">@interface</span><br> */</div>function Shape() {};<br>Shape.prototype.draw = function() {};<br><br><div class="comment" >/**<br> * <span class="doctag">@constructor</span><br> * <span class="doctag">@implements</span> {Shape}<br> */</div>function Square() {};<br>Square.prototype.draw = function() {<br> ...<br>};</div>)|&spanclass(keywd2){@constructor}と共に使用し、あるクラスがインタフェースを実装していることを示します。型を囲む波括弧は省略可能です。|
|@inheritDoc|&html(<div class="tt3" ><span class="keywd2" >@inheritDoc</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag" >@inheritDoc</span><br> */</div>project.SubClass.prototype.toString() {<br> <span class="comment">// ...</span><br>};</div>)|''非推奨。&spanclass(keywd){@override}を使ってください。''&br()&br()サブクラスのメソッド・プロパティが、スーパークラスのメソッド・プロパティを意図的に隠蔽しており、全く同じJSDocコメントを持つことを示します。&spanclass(keywd){@inheritDoc}は&spanclass(keywd){@override}を包含する点に注意してください。|
|@interface|&html(<div class="tt3" ><span class="keywd2" >@interface</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * 形状。<br> * <span class="doctag">@interface</span><br> */</div>function Shape() {};<br>Shape.prototype.draw = function() {};<br><br><div class="comment" >/**<br> * 多角形。<br> * <span class="doctag">@interface</span><br> * <span class="doctag">@extends</span> {Shape}<br> */</div>function Polygon() {};<br>Polygon.prototype.getSides = function() {};</div>)|その関数がインタフェースであることを示すために使います。|
|@lends|&html(<div class="tt3" ><span class="keywd2" >@lends オブジェクト名<br>@lends {オブジェクト名}</span><br><br>例:<div class="bq_m" >goog.object.extend(<br> Button.prototype,<br> <span class="comment">/** <span class="doctag">@lends</span> {Button.prototype} */</span> {<br> isButton: function() { return true; }<br> });</div>)|オブジェクトリテラルのキーが他のオブジェクトのプロパティとして扱われるべきであることを示します。このアノテーションはオブジェクトリテラルにだけ付けられます。&br()&br()他のアノテーションとは異なり、波括弧の中の名前はクラス名ではなくオブジェクト名である点に注意してください。それはプロパティが "lent"(貸与)されているオブジェクトの名前です。例えば&spanclass(keywd){@type {Foo}} は "Fooのインスタンス" を意味しますが、&spanclass(keywd){@lends {Foo}} は "Fooのコンストラクタ関数" のことです。&br()&br()このアノテーションについてのより詳しい説明は&blanklink(JSDoc Toolkit のドキュメント){http://code.google.com/p/jsdoc-toolkit/wiki/TagLends}(&blanklink(日本語){http://www12.atwiki.jp/aias-jsdoctoolkit/pages/34.html})を参照してください。|
|@license or @preserve|&html(<div class="tt3" ><span class="keywd2" >@license 説明文</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag">@preserve</span> Copyright 2009 SomeThirdParty.<br> * このファイルに関する完全なライセンス条項と<br> * 著作権表示を記載します。文章は複数行にわたっても構いませんが、<br> * 必ず末尾は "*/" で閉じられている必要があります。<br> */</div></div>)|&spanclass(keywd2){@license}または&spanclass(keywd){@preserve}が付けられたコメントはCompilerの処理から保護され、コンパイルされたコードよりも前に出力されます。コンパイルの影響を受けないことから、このアノテーションは重要な通知(ライセンスや著作権のような)を行うのに向いています。改行もそのまま残されます。|
|@noalias|&html(<div class="tt3" ><span class="keywd2" >@noalias</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag">@noalias</span> */</div>function Range() {}</div>)|Externファイルの中で使い、この変数または関数に別名を付けてはならないことをCompilerに示します。|
|@nocompile|&html(<div class="tt3" ><span class="keywd2" >@nocompile</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag">@nocompile</span> */</div><br><div class="comment">// JavaScriptコード</div>)|ファイルの先頭に記述し、このファイルのコードをパースするだけでコンパイルしないようコンパイラへ伝えます。このアノテーションは、コンパイルが意図されていない、またはコンパイルテストから除外すべきコード(例えば、ブートストラップコード)に対して使用します。控えめに使ってください。|
|@nosideeffects|&html(<div class="tt3" ><span class="keywd2" >@nosideeffects</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag" >@nosideeffects</span> */</div>function noSideEffectsFn1() {<div class="comment"> // ...</div>};<br><div class="comment">/** <span class="doctag" >@nosideeffects</span> */</div>var noSideEffectsFn2 = function() {<div class="comment"> // ...</div>};<br><div class="comment">/** <span class="doctag" >@nosideeffects</span> */</div>a.prototype.noSideEffectsFn3 = function() {<div class="comment"> // ...</div>};</div>)|関数やコンストラクタに付けられ、それらの呼び出しが他のコードに影響を及ぼさないことを示します。このアノテーションはCompilerに対し、戻り値が使用されていない場合にそれらの関数を削除することを許可します。|
|@override|&html(<div class="tt3" ><span class="keywd2" >@override</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag">@return</span> {string} project.SubClassの人間が理解できる表現。<br> * <span class="doctag">@override</span><br> */</div>project.SubClass.prototype.toString = function() {<br> <span class="comment">// ...</span><br>};</div>)|サブクラスのメソッド・プロパティが、スーパークラスのメソッド・プロパティを意図的に隠蔽していることを示します。コメントにこれ以外の記述が含まれない場合、スーパークラスで書かれた内容がサブクラスに引き継がれます。|
|@param|&html(<div class="tt3" ><span class="keywd2" >@param {型名} 変数名 説明文</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * 各項目のBazを問い合わせます。<br> * <span class="doctag" >@param</span> {number} groupNum 問い合わせのためのサブグループID。<br> * <span class="doctag" >@param</span> {string|number|null} term 項目名、<br> * または項目ID、もしnullの場合は全て検索します。<br> */</div>goog.Baz.prototype.query = function(groupNum, term) {<br> <span class="comment" >// ...</span><br>};</div></div>)|メソッド、関数、コンストラクタに対し、それらの引数を説明するために使用します。&br()&br()&link(型名){JavaScriptのデータ型}は必ず波括弧で括られていなければなりません。型名が省略された場合、Compilerは型チェックを行いません。|
|@private|&html(<div class="tt3" ><span class="keywd2" >@private</span><br><span class="keywd2" >@private {型名}</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * このロガーを監視しているハンドラの配列。<br> * <span class="doctag">@private</span> {!Array.<Function>}<br> */</div>this.handlers_ = [];</div></div>)|メソッド・プロパティ名の末尾にアンダースコアを付加する仕様と組み合わせて、メンバが&link_anchor(visibility,pageid=15){private}であり、オーバーライドできないことを示します。|
|@protected|&html(<div class="tt3" ><span class="keywd2" >@protected</span><br><span class="keywd2" >@protected {型名}</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * 指定されたDOM要素をコンポーネントのルート要素として設定します。<br> * <span class="doctag">@param</span> {Element} element コンポーネントのルート要素<br> * <span class="doctag">@protected</span><br> */</div>goog.ui.Component.prototype.setElementInternal = function(element) {<br> <span class="comment" >// ...</span><br>};</div></div>)|メソッド・プロパティが&link_anchor(visibility,pageid=15){protected}であることを示します。名前の末尾にアンダースコアを付けてはいけません。|
|@public|&html(<div class="tt3" ><span class="keywd2" >@public</span><br><span class="keywd2" >@public {型名}</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * イベント内部のキャプチャ/バブリング処理をキャンセルするかどうか<br> * <span class="doctag">@public</span> {boolean}<br> * <span class="doctag">@suppress</span> {visibility} これをこのパッケージの外部から参照すべき<br> * ではありません。<br> */</div>goog.events.Event.prototype.propagationStopped_ = false;</div></div>)|メソッド・プロパティがpublicであることを示します。変数やプロパティはデフォルトでpublicなので、このアノテーションはめったに必要とされません。古いコードの中で、privateを表す名前を簡単に書き換えられないときにだけ使用してください。|
|@return|&html(<div class="tt3" ><span class="keywd2" >@return {型名} 説明文</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * <span class="doctag" >@return</span> {string} 最後の項目の16進数表記のID<br> */</div>goog.Baz.prototype.getLastId = function() {<br> <span class="comment" >// ...</span><br> return id;<br>};</div></div>)|メソッドと関数に対し、それらの戻り値を説明するために使用します。論理型の戻り値の説明では、"コンポーネントが見えるならtrue、そうでなければfalse" よりも "コンポーネントが見えるかどうか" の方が良い書き方です。戻り値が無い場合、&spanclass(keywd){@return}タグは使わないで下さい。&br()&br()&link(型名){JavaScriptのデータ型}は必ず波括弧で括られていなければなりません。型名が省略された場合、Compilerは型チェックを行いません。|
|@see|&html(<div class="tt3" ><span class="keywd2" >@see リンク</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * むやみに項目を追加します。<br> * <span class="doctag" >@see</span> #addSafely<br> * <span class="doctag" >@see</span> goog.Collect<br> * <span class="doctag" >@see</span> goog.RecklessAdder#add</div> ...</div>)|他のクラス、関数、メソッドへの参照を記載します。|
|@struct|&html(<div class="tt3" ><span class="keywd2" >@struct 説明文</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag">@constructor</span><br> * <span class="doctag">@struct</span><br> */</div>function Foo(x) {<br> this.x = x;<br>}<br>var obj = new Foo(123);<br>var num = obj['x']; <span class="comment">// 警告</span><br>obj.y = "asdf"; <span class="comment">// 警告</span><br><br>Foo.prototype = <span class="comment">/**</span> <span class="doctag">@struct</span> <span class="comment">*/</span> {<br> method1: function() {}<br>};<br>Foo.prototype.method2 = function() {}; <span class="comment">// 警告</span></div>)|コンストラクタ(左の例の&spanclass(keywd){Foo})に&spanclass(keywd){@struct}が付けられた場合、&spanclass(keywd){Foo}オブジェクトのプロパティへのアクセスはドットによる表記法でのみ可能となります。また、生成された&spanclass(keywd){Foo}オブジェクトへ新しいプロパティを追加することはできません。アノテーションをオブジェクトリテラルに直接記述することもできます。|
|@supported|&html(<div class="tt3" ><span class="keywd2" >@supported 説明文</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag">@fileoverview</span> イベントマネージャ<br> * ブラウザ固有のイベントシステムを抽象化した<br> * インタフェースを提供します。<br> * <span class="doctag">@supported</span> これまで IE6 と FF1.5 でテスト済みです。<br> */</div></div>)|&spanclass(keywd2){@fileoverview}を含むコメントブロックで使用し、このファイルの内容をサポートするブラウザを記載します。|
|@suppress|&html(<div class="tt3" ><span class="keywd2" >@suppress {警告1|警告2}</span><br><span class="keywd2" >@suppress {警告1,警告2}</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * <span class="doctag" >@suppress</span> {deprecated}<br> */</div>function f() {<br> deprecatedVersionOfF();<br>}</div>)|ツールからの警告を抑止します。警告の種類が複数ある場合は&spanclass(keywd){|}か&spanclass(keywd){,}で区切ります。|
|@template|&html(<div class="tt3" ><span class="keywd2" >@template</span><br><br>例:<div class="bq_m" ><div class="comment">/**<br> * <span class="doctag" >@param</span> {function(this:T, ...)} fn<br> * <span class="doctag" >@param</span> {T} thisObj<br> * <span class="doctag" >@param</span> {...*} var_args<br> * <span class="doctag" >@template</span> T<br> */</div>goog.bind = function(fn, thisObj, var_args) {<br> ...<br>};</div>)|このアノテーションは&link_anchor(template_types,pageid=17){テンプレート型}を宣言するために使用します。|
|@this|&html(<div class="tt3" ><span class="keywd2" >@this 型名<br>@this {型名}</span><br><br>例:<div class="bq_m" >pinto.chat.RosterWidget.extern('getRosterElement',<br><div class="comment">/**<br> * 名簿ウィジェットの要素を返します。<br> * <span class="doctag">@this</span> pinto.chat.RosterWidget<br> * <span class="doctag">@return</span> {Element}<br> */</div>function() {<br> return this.getWrappedComponent_().getElement();<br>});</div>)|特定のメソッドが呼ばれるときのコンテキストの型を表します。thisがプロトタイプメソッドでない関数から参照されているときに必要です。|
|@type|&html(<div class="tt3" ><span class="keywd2" >@type 型名<br>@type {型名}</span><br><br>例:<div class="bq_m" ><div class="comment" >/**<br> * 16進数形式のID。<br> * <span class="doctag">@type</span> {string}<br> */</div>var hexId = hexId;</div>)|変数、プロパティ、式の&link(データ型){JavaScriptのデータ型}を表します。ほとんどの型において波括弧で囲むことは必須ではありませんが、一貫性のためにそれを強制しているプロジェクトもあります。|
|@typedef|&html(<div class="tt3" ><span class="keywd2" >@typedef</span><br><br>例:<div class="bq_m" ><div class="comment">/** <span class="doctag" >@typedef</span> {(string|number)} */</div>goog.NumberLike;<br><br><div class="comment">/** <span class="doctag" >@param</span> {goog.NumberLike} x 数値か文字列 */</div>goog.readNumber = function(x) {<br> ...<br>}</div>)|このアノテーションは&link_anchor(typedefs,pageid=17){複雑な型}に別名を付けるために使用します。|
サードパーティのコードの中で、上記以外の種類のJSDocアノテーションが使われているのを目にするかもしれません。それらは&blanklink(JSDoc Toolkitタグリファレンス){http://code.google.com/p/jsdoc-toolkit/wiki/TagReference}に現れるものですが、Googleのコーディングルールでは今のところ使用を推奨しません。以下のアノテーションは将来の利用に備えて「予約されている」名前だと考えてください:
- @augments
- @argument
- @borrows
- @class
- @constant
- @constructs
- @default
- @event
- @example
- @field
- @function
- @ignore
- @inner
- @link
- @memberOf
- @name
- @namespace
- @property
- @public
- @requires
- @returns
- @since
- @static
- @version
----
2013-10-16T00:16:29+09:00
1381850189
-
メニュー
https://w.atwiki.jp/aias-jsstyleguide2/pages/2.html
***サイト内検索
#search2(or,submit=検索, title=,size=60,ignore=own)
----
**コンテンツ
-&link2(トップページ)
#divclass(space){}
-&link(言語仕様に関するルール){JavaScriptの言語仕様に関するルール}
--&link_anchor(var,pageid=13){var}
--&link_anchor(constants,pageid=13){定数}
--&link_anchor(semicolons,pageid=13){セミコロン}
--&link_anchor(nested_functions,pageid=13){ネストされた関数}
--&link_anchor(function_declarations_within_blocks,pageid=13){ブロック内での関数宣言}
--&link_anchor(exceptions,pageid=13){例外}
--&link_anchor(custom_exceptions,pageid=13){独自の例外}
--&link_anchor(standards_features,pageid=13){標準機能}
--&link_anchor(wrapper_objects_for_primitive_types,pageid=13){プリミティブ型のラッパーオブジェクト}
--&link_anchor(multi_level_prototype_hierarchies,pageid=13){多段階のプロトタイプ階層}
--&link_anchor(method_and_property_definitions,pageid=13){メソッドとプロパティの定義}
--&link_anchor(delete,pageid=13){delete}
--&link_anchor(closures,pageid=13){クロージャ}
--&link_anchor(eval,pageid=13){eval()}
--&link_anchor(with,pageid=13){with()}
--&link_anchor(this,pageid=13){this}
--&link_anchor(for_in_loop,pageid=13){for-in ループ}
--&link_anchor(associative_arrays,pageid=13){連想配列}
--&link_anchor(multiline_string_literals,pageid=13){複数行の文字列リテラル}
--&link_anchor(array_and_object_literals,pageid=13){配列リテラルとオブジェクトリテラル}
--&link_anchor(modifying_prototypes_of_builtin_objects,pageid=13){組込みオブジェクトのプロトタイプの書き換え}
--&link_anchor(ies_conditional_comments,pageid=13){Internet Explorerの条件付きコメント}
#divclass(space){}
-&link(スタイルに関するルール){JavaScriptのスタイルに関するルール}
--&link_anchor(naming,pageid=15){命名規則}
---&link_anchor(properties_and_methods,pageid=15){プロパティとメソッド}
---&link_anchor(method_and_function_parameter,pageid=15){メソッドと関数のパラメータ}
---&link_anchor(getters_and_setters,pageid=15){GetterとSetter}
---&link_anchor(accessor_functions,pageid=15){アクセサ関数}
---&link_anchor(namespaces,pageid=15){名前空間}
---&link_anchor(filenames,pageid=15){ファイル名の命名規則}
--&link_anchor(deferred_initialization,pageid=15){変数初期化の遅延}
--&link_anchor(explicit_scope,pageid=15){明示的なスコープ}
--&link_anchor(code_formatting,pageid=15){コードのフォーマット}
---&link_anchor(curly_braces,pageid=15){波括弧}
---&link_anchor(array_and_object_initializers,pageid=15){配列とオブジェクトの初期化}
---&link_anchor(function_arguments,pageid=15){関数の引数}
---&link_anchor(passing_nonymous_functions,pageid=15){無名関数の引渡し}
---&link_anchor(aliasing_with_goog_scope,pageid=15){goog.scopeによる別名}
---&link_anchor(indenting_wrapped_lines,pageid=15){行折り返しのインデント}
---&link_anchor(blank_lines,pageid=15){空行}
---&link_anchor(binary_and_ternary_operators,pageid=15){二項または三項の演算子}
--&link_anchor(parentheses,pageid=15){丸括弧}
--&link_anchor(strings,pageid=15){文字列}
--&link_anchor(visibility,pageid=15){可視性(privateまたはprotectedなフィールド)}
--&link_anchor(js_types,pageid=15){JavaScriptのデータ型}
---&link_anchor(js_type_language,pageid=17){JavaScriptの型言語}
---&link_anchor(types_in_js,pageid=17){JavaScriptで使えるデータ型}
---&link_anchor(type_casts,pageid=17){型キャスト}
---&link_anchor(nullable_vs_optional_parameters_and_properties,pageid=17){そのパラメータ・プロパティは「Nullを許す」のか「省略できる」のか}
---&link_anchor(typedefs,pageid=17){型定義}
---&link_anchor(template_types,pageid=17){テンプレート型}
---&link_anchor(enums,pageid=17){列挙型}
--&link_anchor(comments,pageid=15){コメント}
---&link_anchor(comment_syntax,pageid=14){コメントの構文}
---&link_anchor(jsdoc_indentation,pageid=14){JSDocのインデント}
---&link_anchor(html_in_jsdoc,pageid=14){JSDocの中のHTML}
---&link_anchor(top_file_level_comments,pageid=14){トップ(ファイル)レベルのコメント}
---&link_anchor(class_comments,pageid=14){クラスへのコメント}
---&link_anchor(method_and_function_comments,pageid=14){メソッドと関数へのコメント}
---&link_anchor(property_comments,pageid=14){プロパティへのコメント}
---&link_anchor(jsdoc_tag_reference,pageid=14){JSDocタグリファレンス}
--&link_anchor(providing_dependencies_with_goog_provide,pageid=15){goog.provideによる依存関係の規定}
--&link_anchor(compiling,pageid=15){コンパイル}
--&link_anchor(tips_and_tricks,pageid=15){ヒントとテクニック}
---&link_anchor(boolean_expressions,pageid=15){論理値表現}
---&link_anchor(conditional_ternary_operator,pageid=15){条件(三項)演算子}
---&link_anchor(and_and_or,pageid=15){&& と ||}
---&link_anchor(iterating_over_node_lists,pageid=15){ノードリストへの反復処理}
#divclass(space){}
#divclass(space){}
-&link(){Closure Linterの使い方}
----
**リンク
-&blanklink(Google JavaScript Style Guide){http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml} (原文)
#divclass(space){}
-&blanklink(Closure Linter){http://code.google.com/intl/ja/closure/utilities/index.html}
----
**更新履歴
#recent(20)
----
-管理人:aiaswood
-ご意見・お問い合わせ等は&br()&mailto(aiaswood@aias-wood.jp){こちら}までどうぞ
2013-10-14T21:39:29+09:00
1381754369
-
JavaScriptのデータ型
https://w.atwiki.jp/aias-jsstyleguide2/pages/17.html
#include_js(http://www38.atwiki.jp/aias-jsstyleguide2/?cmd=upload&act=open&page=%E3%83%88%E3%83%83%E3%83%97%E3%83%9A%E3%83%BC%E3%82%B8&file=goog_style_guide.js)
#divclass(page_title){
&this_page()
}
JSDocへのデータ型の記述は、できるだけ具体的かつ正確に行ってください。我々のサポートする型のスタイルは&blanklink(EcmaScript 4 仕様){http://wiki.ecmascript.org/doku.php?id=spec:spec}に基づいています。
*** &aname(js_type_language,option=nolink){JavaScriptの型言語}
ES4の提案にはJavaScriptのデータ型を定義する言語が含まれていました。この言語をJSDoc内で用い、関数パラメータや戻り値の型を表現します。
ES4提案の進展に伴い、その型言語も変化しています。Compilerは古い構文もサポートしていますが、現在それらは非推奨となっています。
|構文名|構文|説明|非推奨の構文|h
|Primitive Type|JavaScriptに含まれる5種類のプリミティブ型: &spanclass(keywd){{null}}, &spanclass(keywd){{undefined}}, &spanclass(keywd){{boolean}}, &spanclass(keywd){{number}}, &spanclass(keywd){{string}}|シンプルな型名称||
|Instance Type|&spanclass(keywd2){{Object}}&br()Objectのインスタンスもしくはnull&br()&br()&spanclass(keywd2){{Function}}&br()Functonのインスタンスもしくはnull&br()&br()&spanclass(keywd2){{EventTarget}}&br()EventTargetインタフェースを実装するコンストラクタのインスタンスもしくはnull|コンストラクタまたはインタフェースのインスタンスであることを表します。&br()&br()コンストラクタ関数は&spanclass(keywd){@cpnstructor}JSDocタグによって定義されます。インタフェース関数は&spanclass(keywd){@interface}JSDocタグによって定義されます。&br()&br()デフォルトで、Instance Typeはnullを許可します。このタイプはnullを許す唯一のものです。この表に含まれる他の構文はデフォルトでnullを許可しません。||
|Enum Type|&spanclass(keywd2){{goog.events.EventType}}&br()&spanclass(keywd2){goog.events.EventType}の列挙値で初期化されたオブジェクトリテラルのプロパティのどれか|列挙型の変数はオブジェクトリテラルもしくは他の列挙型変数の別名で、&spanclass(keywd){@enum}JSDocタグがアノテートされていなければなりません。このオブジェクトリテラルのプロパティが、列挙値の実体となります。列挙型の構文については&link_anchor(project_myenum){こちら}で定義されています。&br()&br()注意:この型は、我々の型システムのうちES4仕様に含まれない数少ないもののひとつです。||
|Type Application|&spanclass(keywd2){{Array.<string>}}&br()文字列の配列&br()&br()&spanclass(keywd){{Object.<string, number>}}&br()キーが文字列、値が数値のオブジェクト|型引数のセットを付記し、型をパラメータ化します。考え方はJavaのジェネリクスによく似ています。||
|Type Union|&spanclass(keywd2){{(number|boolean)}}&br()数値または論理値|値の型がAまたはBであることを表します。&br()&br()この型が最上位の式で使われる場合、丸括弧は省略しても構いません。しかしそうでない場合は、曖昧さを避けるために丸括弧を付けてください。&br()&spanclass(keywd){{number|boolean}}&br()&spanclass(keywd){{function(): (number|boolean)}}|&spanclass(keywd){{(number,boolean)}}, &spanclass(keywd){{(number||boolean)}}|
|Nullable Type|&spanclass(keywd2){{?number}}&br()数値またはNULL。|Unionの省略形で、何らかの型もしくはnullであることを表します。この型は糖衣構文です。|&spanclass(keywd){{number?}}|
|Non-nullable Type|&spanclass(keywd2){{!Object}}&br()Object型ですが、nullは許されません。|この型がnullを許容しないことを表します。殆どの場合、デフォルトでnullを許すInstance Typeに対して使用されます。|&spanclass(keywd){{Object!}}|
|Record Type|&spanclass(keywd2){{{myNum: number, myObject}}}&br()型指定されたメンバを持つ無名オブジェクト|値が指定された型のメンバを持つオブジェクトであることを表します。左のケースでは、&spanclass(keywd){myNum}は数値、&spanclass(keywd){myObject}はどの型でも取れるプロパティです。&br()&br()波括弧は構文の一部であることに注意してください。例えば&spanclass(keywd){Array}が&spanclass(keywd){length}というプロパティを持つオブジェクトの配列であることを示すには、&spanclass(keywd){Array.<{length}>}のように書きます。||
|Function Type|&spanclass(keywd2){{function(string, boolean)}}&br()2つの引数(文字列と論理値)を取り、戻り値が指定されていない関数。|関数を定義します。||
|Function Return Type|&spanclass(keywd2){{function(): number}}&br()引数を取らず、数値を戻り値として返す関数。|関数の戻り値の型を定義します。||
|Function this Type|&spanclass(keywd2){{function(this:goog.ui.Menu, string)}}&br()文字列の引数1つをとり、&spanclass(keywd){goog.ui.Menu}のコンテキストで実行される関数。|関数のコンテキストの型を定義します。||
|Function new Type|&spanclass(keywd2){{function(new:goog.ui.Menu, string)}}&br()文字列の引数を1つ取るコンストラクタ関数。'new'キーワードと共にコールされるときには&spanclass(keywd){goog.ui.Menu}のインスタンスを生成します。|コンストラクタによって作成される型を定義します。||
|Variable arguments|&spanclass(keywd2){{function(string, ...[number]): number}}&br()引数として文字列を1つと、可変個数の数値を取る関数。|関数に個数の変化する引数を定義します。||
|Variable arguments (in @param annotations)|&spanclass(keywd2){@param {...number} var_args}&br()可変個数の引数を取るようアノテートされた関数。|可変個数の引数を受け取れるようアノテートされた関数を定義します。||
|Function &link_anchor(nullable_vs_optional_parameters_and_properties){optional arguments}|&spanclass(keywd2){{function(?string=, number=)}}&br()省略可能な、nullでもよい文字列型の引数と、省略可能な数値型の引数を取る関数。&spanclass(keywd){=}は関数型の宣言の中でのみ使います。|関数の省略可能な引数を定義します。||
|Function &link_anchor(nullable_vs_optional_parameters_and_properties){optional arguments} (in @param annotations)|&spanclass(keywd2){@param {number=} opt_argument}&br()数値型の省略可能なパラメータ。|省略可能な引数を受け取れるようアノテートされた関数を定義します。||
|The ALL Type|&spanclass(keywd2){{*}}|その変数がどのような型でも取れることを表します。||
|The UNKNOWN Type|&spanclass(keywd2){{?}}|その変数がどのような型でも取れ、Compilerはそれを使った型チェックを行ってはならないことを表します。||
*** &aname(types_in_js,option=nolink){JavaScriptで使えるデータ型}
|型名の例|値の例|説明|h
|number|&spanclass(keywd2){1&br()1.0&br()-5&br()1e5&br()Math.PI}||
|Number|&spanclass(keywd2){new Number(true)}|&link_anchor(wrapper_objects_for_primitive_types){Numberオブジェクト}|
|string|&spanclass(keywd2){'Hello'&br()"World"&br()String(42)}|文字列値|
|String|&spanclass(keywd2){new String('Hello')&br()new String(42)}|&link_anchor(wrapper_objects_for_primitive_types){Stringオブジェクト}|
|boolean|&spanclass(keywd2){true&br()false&br()Boolean(0)}|論理値|
|Boolean|&spanclass(keywd2){new Boolean(true)}|&link_anchor(wrapper_objects_for_primitive_types){Booleanオブジェクト}|
|RegExp|&spanclass(keywd2){new RegExp('hello')&br()/world/g}||
|Date|&spanclass(keywd2){new Date&br()new Date()}||
|null|&spanclass(keywd2){null}||
|undefined|&spanclass(keywd2){undefined}||
|void|&spanclass(keywd2){function f() {&br() return;&br()}}|戻り値なし|
|Array|&spanclass(keywd2){['foo', 0.3, null]&br()[]}|型指定のない配列|
|Array.<number>|&spanclass(keywd2){[11, 22, 33]}|数値の配列|
|Array.<Array.<string>>|&spanclass(keywd2){[['one', 'two', 'three'], ['foo', 'bar']]}|文字列の配列の配列|
|Object|&spanclass(keywd2){{}&br(){foo: 'abc', bar: 123, baz: null}}||
|Object.<string>|&spanclass(keywd2){{'foo': 'bar'}}|文字列の値を持つオブジェクト|
|Object.<number, string>|&spanclass(keywd2){var obj = {};&br()obj[1] = 'bar';}|キーが数値で値が文字列のオブジェクト。&br()&br()JavaScriptではオブジェクトのキーは暗黙的に文字列に変換される点に注意してください。従って&spanclass(keywd){obj['1'] == obj[1]}です。また for...in ループの中でもキーは常に文字列です。しかしCompilerはオブジェクトのキーをインデックス化する際、その型を識別します。|
|Function|&spanclass(keywd2){function(x, y) {&br() return x * y;&br()}}|&link_anchor(wrapper_objects_for_primitive_types){Functionオブジェクト}|
|function(number, number): number|&spanclass(keywd2){function(x, y) {&br() return x * y;&br()}}|関数|
|SomeClass&aname(constructor-tag,option=nolink){ }|&spanclass(keywd2){/** @constructor */&br()function SomeClass() {}&br()&br()new SomeClass();}||
|SomeInterface|&spanclass(keywd2){/** @interface */&br()function SomeInterface() {}&br()&br()SomeInterface.prototype.draw = function() {};}||
|project.MyClass|&spanclass(keywd2){/** @constructor */&br()project.MyClass = function () {}&br()&br()new project.MyClass()}||
|project.MyEnum&aname(project_myenum,option=nolink){ }|&spanclass(keywd2){/** @enum {string} */&br()project.MyEnum = {&br() /** 青色 */&br() BLUE: '#0000dd',&br() /** 赤色 */&br() RED: '#dd0000'&br()};}|&link_anchor(enums){列挙型}&br()&br()列挙値に対するJSDocコメントは省略可能です。|
|Element|&spanclass(keywd2){document.createElement('div')}|DOM要素|
|Node|&spanclass(keywd2){document.body.firstChild}|DOMノード|
|HTMLInputElement|&spanclass(keywd2){htmlDocument.getElementsByTagName('input')[0]}|DOM要素の型を明示的に指定します。|
*** &anchor(type_casts,option=nolink){型キャスト}
ある式のデータ型を型チェック機能が正確に推測できないケースでは、型キャストコメントを利用できます。型キャストコメントには&spanclass(keywd){@type}アノテーションでデータ型を示し、式は丸括弧で括ります。丸括弧は必須です。
#blockquote(){{{#divclass(comment){{/** &spanclass(doctag){@type} {number} */ (x)
}}
}}}
*** &aname(nullable_vs_optional_parameters_and_properties,option=nolink){そのパラメータ・プロパティは「Nullを許す」のか「省略できる」のか}
JavaScriptは型に厳格でない言語なので、関数パラメータやクラスプロパティにおける「nullを許す」、「省略できる」、「undefined」の微妙な違いを理解しておくことは非常に重要です。
クラスとインタフェースのインスタンスはデフォルトでnullを許します。例として、以下の宣言をみてください:
#blockquote(){{{#divclass(comment){{/**
 (1)* 何かのクラス、何らかの値で初期化されます。
 (1)* &spanclass(doctag){@param} {Object} value 何かの値。
 (1)* &spanclass(doctag){@constructor}
 (1)*/
}}
function MyClass(value) {
#divclass(comment){{
 (2)/**
 (3)* 何かの値。
 (3)* &spanclass(doctag){@type} {Object}
 (3)* &spanclass(doctag){@private}
 (3)*/
}}
 (2)this.myValue_ = value;
}
}}}
上のコードはCompilerに対し、&spanclass(keywd){myValue_}プロパティが値として持つのはオブジェクトかnullのどちらかだと伝えています。もし &spanclass(keywd){myValue_}プロパティが決してnullとならないのなら、こう宣言されるべきです:
#blockquote(){{{#divclass(comment){{/**
 (1)* 何かのクラス、nullでない何らかの値で初期化されます。
 (1)* &spanclass(doctag){@param} {!Object} value 何かの値。
 (1)* &spanclass(doctag){@constructor}
 (1)*/
}}
function MyClass(value) {
#divclass(comment){{
 (2)/**
 (3)* 何かの値。
 (3)* &spanclass(doctag){@type} {!Object}
 (3)* &spanclass(doctag){@private}
 (3)*/
}}
 (2)this.myValue_ = value;
}
}}}
この場合、もしコードのどこかで&spanclass(keywd){MyClass}がnull値で初期化されていることをCompilerが検出すると、Compilerから警告が発せられます。
省略されたパラメータはおそらくランタイムによってundefinedとして扱われます。それらがオブジェクトのプロパティに代入されるのであれば、プロパティもまたそれに応じて適切に宣言されていなければなりません:
#blockquote(){{{#divclass(comment){{/**
 (1)* 何かのクラス、省略可能な何らかの値で初期化されます。
 (1)* &spanclass(doctag){@param} {Object=} opt_value 何かの値(省略可)。
 (1)* &spanclass(doctag){@constructor}
 (1)*/
}}
function MyClass(value) {
#divclass(comment){{
 (2)/**
 (3)* 何かの値。
 (3)* &spanclass(doctag){@type} {Object|undefined}
 (3)* &spanclass(doctag){@private}
 (3)*/
}}
 (2)this.myValue_ = value;
}
}}}
上のコードはCompilerに対し、&spanclass(keywd){myValue_}の値はオブジェクトかnull、あるいはundefinedのままであると伝えています。
省略可能なパラメータ&spanclass(keywd){opt_value}の型が&spanclass(keywd){{Object=}}と宣言されており、&spanclass(keywd){{Object|undefined}}ではないことに注意してください。それは、省略可能なパラメータが undefined でありうることが定義上明らかだからです。そのことを明示的に宣言しても不都合はありませんが、本来必要ないだけでなく、コードも読みにくくなってしまいます。
最後に、nullを許すことと省略可能であることは直交的な性質である点に注意してください。以下の4つの宣言は全て異なった意味を持っています:
#blockquote(){{{#divclass(comment){{/**
 (1)* 4つの引数を取ります。そのうち2つはnullを許容し、2つは省略可能です。
 (1)* &spanclass(doctag){@param} {!Object} nonNull 必須(undefinedは不可)、nullは不可。
 (1)* &spanclass(doctag){@param} {Object} mayBeNull 必須(undefinedは不可)、nullでもよい。
 (1)* &spanclass(doctag){@param} {!Object=} opt_nonNull 省略可 (undefinedでもよい)、しかし値があるなら、
 (1)* (5)それはnullであってはならない!
 (1)* &spanclass(doctag){@param} {Object=} opt_mayBeNull 省略可 (undefinedでもよい)、nullでもよい。
 (1)*/
}}
function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) {
 (1)&spanclass(comment){// ...}
};
}}}
*** &anchor(typedefs,option=nolink){型定義}
時々、型の指定が複雑になってしまうことがあります。例えば、DOM要素のコンテンツを受け取る関数があるとしましょう:
#blockquote(){{{#divclass(comment){{/**
 (1)* &spanclass(doctag){@param} {string} tagName
 (1)* &spanclass(doctag){@param} {(string|Element|Text|Array.<Element>|Array.<Text>)} contents
 (1)* &spanclass(doctag){@return} {Element}
 (1)*/
}}
goog.createElement = function(tagName, contents) {
 (2)...
};
}}}
&spanclass(keywd2){@typedef}タグを使うと、よく使われるデータ型の組み合わせを1つの型として定義することができます。例えばこうです:
#blockquote(){{{#divclass(comment){{/** &spanclass(doctag){@typedef} {(string|Element|Text|Array.<Element>|Array.<Text>)} */
}}
goog.ElementContent;
#divclass(comment){{
/**
 (1)* &spanclass(doctag){@param} {string} tagName
 (1)* &spanclass(doctag){@param} {goog.ElementContent} contents
 (1)* &spanclass(doctag){@return} {Element}
 (1)*/
}}
goog.createElement = function(tagName, contents) {
 (2)...
};
}}}
*** &aname(template_types,option=nolink){テンプレート型}
Compilerが行うテンプレート型のサポートは限定的です。それは関数リテラル内の&spanclass(keywd){this}の型を、&spanclass(keywd){this}を指定する引数の型と値の有無から推測するだけです。
#blockquote(){{{#divclass(comment){{/**
 (1)* &spanclass(doctag){@param} {function(this:T, ...)} fn
 (1)* &spanclass(doctag){@param} {T} thisObj
 (1)* &spanclass(doctag){@param} {...*} var_args
 (1)* &spanclass(doctag){@template} T
 (1)*/
}}
goog.bind = function(fn, thisObj, var_args) {
 (2)...
};
&spanclass(comment){// おそらくプロパティが存在しないという警告が出力されます。}
goog.bind(function() { this.someProperty; }, new SomeClass());
&spanclass(comment){// thisがundefinedであるという警告が出力されます。}
goog.bind(function() { this.someProperty; });
}}}
*** &aname(enums,option=nolink){列挙型}
&color(red){訳注:2.28版以降列挙型に関する以下の説明は削除されていますが、コーディングルールの理解には必要と考え記載します。}
#blockquote(){{{#divclass(comment){{/**
 (1)* 3つの状態を値にもつ列挙型。
 (1)* &spanclass(doctag){@enum} {number}
 (1)*/
}}
project.TriState = {
 (2)TRUE: 1,
 (2)FALSE: -1,
 (2)MAYBE: 0
};
}}}
列挙型は有効な&link_anchor(types_in_js){データ型}の1つである点に注意して下さい。列挙型はパラメータの型指定などに使用できます。
#blockquote(){{{#divclass(comment){{/**
 (1)* プロジェクトの状態を設定します。
 (1)* &spanclass(doctag){@param} {project.TriState} state 新しいプロジェクトの状態
 (1)*/
}}
project.setState = function(state) {
 (1)&spanclass(comment){// ...}
};
}}}
----
2013-08-11T12:42:42+09:00
1376192562
-
Closure Linterの使い方
https://w.atwiki.jp/aias-jsstyleguide2/pages/16.html
#divclass(page_title){
&this_page()
}
- このページは &blanklink(){http://code.google.com/intl/ja/closure/utilities/docs/linter_howto.html} の日本語訳です。
- &blanklink(Closure Linter){http://code.google.com/intl/ja/closure/utilities/index.html}はJavaScriptのコードスタイルがGoogleのスタイルガイドに適合しているかをチェックするツールで、Google自身が提供しています。またエラーを警告するだけでなく、エラー箇所を自動的に修正してくれる機能も持っています。
このドキュメントは Closure Linter のインストールと利用の仕方を解説するものです。
** Closure Linter のインストール
Closure Linter のインストールには、Python の&spanclass(keywd){easy_install}ユーティリティを使ってください。
*** Linux
LinuxにClosure Linter をインストールするには、以下のコマンドを実行してください。
#blockquote(){{$ cd /tmp
/tmp$ sudo easy_install &nolink(http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz)
}}
*** Mac OS X
Mac OS XにClosure Linter をインストールするには、以下のコマンドを実行してください。
#blockquote(){{$ sudo easy_install &nolink(http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz)
}}
*** Windows
Windowsに Closure Linter をインストールするには:
+ &blanklink(Windows版Python){http://www.python.org/download/windows/}をダンロード、インストールします。
+ &blanklink(Easy Install){http://peak.telecommunity.com/DevCenter/EasyInstall#installing-easy-install}をインストールします。
+ 以下のコマンドを実行します。
#blockquote(){{> easy_install &nolink(http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz)
}}
- ''注意'': Closure LinterのWindowsサポートは試験的です。
** スタイルの問題点を発見する
Closure Linterで単独のファイルを処理するには、こうします:
#blockquote(){{$ gjslint path/to/my/file.js
}}
このような結果が得られます:
#blockquote(){{Line 46, E:0110: Line too long (87 characters).
Line 54, E:0214: Missing description in @return tag
Line 66, E:0012: Illegal semicolon after function declaration
Line 150, E:0120: Binary operator should go on previous line "+"
Line 175, E:0011: Missing semicolon after function assigned to a variable
Line 210, E:0121: Illegal comma at end of array literal
Line 220, E:0002: Missing space before ":"
}}
ディレクトリ全体を再帰的にチェックすることもできます。こうしてください:
#blockquote(){{$ gjslint -r path/to/my/directory
}}
デフォルトでは、Closure Linter はJsDocアノテーションが正しく記述されているかをチェックします。もしあなたのプロジェクトでJsDocアノテーションが無いことをチェック対象にしたくなければ、次のようにして機能を無効にしてください:
#blockquote(){{$ gjslint --nojsdoc -r path/to/my/directory
}}
このフラグによってJsDocアノテーションの有無はチェックされなくなりますが、記述されているJsDocアノテーションの内容が正しいかどうかの検証は相変わらず行われます。
*** --strict フラグ
もしスペースの使い方やJsDocの型、@authorタグなどについて Closure Linter により厳格なルールを適用させたければ、&spanclass(keywd){--strict}コマンドラインフラグを使用してください。また&blanklink(Closure Library){http://code.google.com/intl/ja/closure/library/}にコードを寄贈する場合は、&spanclass(keywd){--strict}を必ず使わなければなりません。
- ''訳注'': &spanclass(keywd2){--help}フラグを使って、利用可能なオプションの完全なリストを参照することができます。
** スタイルの問題点を修正する
上に示したどのコマンドでも、&spanclass(keywd){gjslint}を&spanclass(keywd){fixjsstyle}に置き換えると、&spanclass(keywd){gjslint}によって検出されたエラーの多くを自動的に修正することができます。
例えばこのようにします:
#blockquote(){{$ fixjsstyle path/to/file1.js path/to/file2.js
}}
&spanclass(keywd2){fixjsstyle}を使用する前に、ファイルをバックアップするか、それらをソース管理システムに保管しておくべきです。あなたが望まないようなかたちでスクリプトが改変されてしまう可能性もあるからです。
- ''訳注'': &spanclass(keywd2){--help}フラグを使って、利用可能なオプションの完全なリストを参照することができます。
----
2011-08-28T21:48:29+09:00
1314535709