Hatena::ブログ(Diary)

三等兵

2009-12-13

JavaScript初心者におくる24のグレイトなtips

私が作ったわけではなく海外の記事です。自分も学習してみました。

phpスポーツ啓発日誌や、コカトリスさんや、アイスクレアームパラダイスさんのような、品質の良い訳は私にはできませんので見出しは意訳もしくは誤訳、文章は無視して訳してません。かつ、私がいろいろコードや文章つけたしてます。内容的にはほとんどズレてはないと思いますが、適当なのでおかしいところがあるかもしれません。

うっとうしい場合は原文をどうぞ。

24 JavaScript Best Practices for Beginners


1. 等価演算子で==使うなよボケ===だろナスチン野郎

ひぃぃぃ。

==|!= だとねー、型は自動に変換されるんすよねー。ねー。

s = '1';
i = 1;
alert(s == i); // true
alert(s === i); //false

えーと、==は「わし、数値も文字列も中身が一緒だったら一緒にしかみえないんや。だから、男も女も同じにしかみえんのや。性別やない、中身なんや…ッ」という具合の今流行りな人なんですねー。===は「あたし、キッチリキチキチタイプがすきやねん。めっちゃすきやねん」という具合な人なんですねー。ねー。関西人じゃないのに関西弁つかってごめんなさいねー。

phpの===ほど評判は悪くないのではりきってどうぞ。


2. evalはバットマンです

Eval = Badだそうです。eval関数というのがあるんですが、それ使うなと。セキュリティ上の問題もあるし、パフォーマンスも低下するのかな。遅くなると思う。この関数は使ったことがないのであれですが、興味があったら検索してみましょ。


3. 波括弧省略する悪い子はいねぇ"ーがー

中括弧ともいいますが。{ }これです。省略できるんすねー。

if(2 === 2)
  alert('等価演算子参上!'); //等価演算子参上!

省略するとこういう書き方ができるわけです。では、たとえば二行にわたり処理を書いたとします。


if(2 === 2)
  alert('等価演算子参上!'); 
  functioncall();

これを書いた残念で仕方が無い男、無残凡夫(むざんぼんぷ)43歳の思惑は次の通り。「(2 === 2)でtrueだったらalert表示してそれからも関数を呼び出すんだぁ。ウフフ。これで、僕も、ギークでクールな男、ギークールマンだ!」と。

上記のプログラムを、無残凡夫は次のプログラムと同じだと思っている。

if(2 === 2){
  alert('等価演算子参上!'); 
  functioncall();
}

if文中に関数が入っていると彼は確信してやりやがったのです。ダメな方向に確信犯。実際のところ無残凡夫が書いた無残なプログラムは、

if(2 === 2){
  alert('等価演算子参上!'); 
}
functioncall();

こういう意味になっちゃうんですねー。ねー。if文に関数が入っていないのです。無残凡夫はギークールマンにはなれず、ダディクールとなってしまいましたとさ…。ねー。

というわけで、波括弧ないと意図しない動作をしてしまったり、パッと見で分かりにくかったりするので、横着しないようにしましょうということでした。ちなみに一行で事たる場合。

if(2 === 2) alert('参上');
//or
if(2 === 2) { alert('参上'); }

と書いていいかな。個人的には下の波括弧入れたのが見やすいと思う。ちなみに三項演算子というのもありますが、

alert((2 === 2) ? '三項参上!':'無残凡夫参上!'); // 三項参上!

可読性あがる?うーん、個人的に見づらいのであんま使いたくないよ。


4. JS Lintを使え!そして私を崇めひれふしなさいふはは

ふははは。

http://www.jslint.com/

JavaScirpt構文チェッカーです。最近はgoogleのClosure Toolsもあるので、そっちでもいいよね。

http://closure-compiler.appspot.com/home


5. スクリプトタグはページの下に置きましょ

そのままなのでお借りします。

<p>And now you know my favorite kinds of corn. </p>
<script type="text/javascript" src="path/to/file.js"></script>
<script type="text/javascript" src="path/to/anotherFile.js"></script>
</body>
</html>

別にヘッダーでも良いと思うんだけどね。document.write系がなかったらdefer属性使っても良いだろうし。

javascript?@defer - Google ????


6. パパfor文の中で変数宣言しちゃうぞーとか、もうアホかとバカかと

これも原文まんま使わせていただきましょう。

ようはfor文の中で変数宣言せずに外でね。ねー。ということですねー。

for(var i = 0; i < someArray.length; i++) {
  var container = document.getElementById('container');
  container.innerHtml += 'my number: ' + i;
  console.log(i);
}

さすがにこれやらんでしょうけども。大変効率が悪いので、

var container = document.getElementById('container');
for(var i = 0, len = someArray.length; i < len;  i++) {
   container.innerHtml += 'my number: ' + i;
   console.log(i);
}

こうやってなるべく外で宣言しましょ。


追記

トラバありがとうございます。ブコメはこれですね。

seiunsky js, tips for 文の中で変数宣言するなって本当か? 変数って関数レベルのスコープになるから、宣言する事のコストではなく、宣言時のgetElementByIdに対するコストを気にしてるんじゃないの? 2009/12/15

http://b.hatena.ne.jp/entry/d.hatena.ne.jp/sandai/20091213/p1

その通りです。さすがにこのサンプルのようなあからさまなことはやらないよなと思って、軽く流してしまったのですが明記しておくべきでした。それから、配列の長さをlenに代入していますが、私はしてもしなくてもどちらでもいいのではないかと思ってスルーしています。でも推奨は先に長さを取得しておくことみたいです。

それからJSはブロックレベルのスコープがありません。なので、

for(var i = 0; i < 10;  i++){
alert(i);
}
//
var i;
for(i = 0; i < 10;  i++){
alert(i);
}

これはどちらも一緒です。

最初は変な気分になりますが慣れたらなんてことないですね。


7. 最速の道は文字列の構築

英語の文章はよくわからん。

今回の例でいえば、おそらくfor文を使ってやらなきゃいけないようにみえる処理も使わなくてもできるんだぜ。そっちの方が速いときもあるんだぜ。クリエイティブなんだぜというようなことだと思う。そういうわけで計測してみました。

//平均3.4ms
var arr = ['item 1', 'item 2', 'item 3'];
var list = '<ul><li>' + arr.join('</li><li>') + '</li></ul>';

//<ul><li>item 1</li><li>item 2</li><li>item 3</li></ul>
document.write(list);

という感じ。平均で3.4msですねー。for文使わずにjoin関数で処理しています。では、私のような初心者がこれをfor文で実現しようとすると、こうかな。

//平均2.9ms
var arr = ['item 1', 'item 2', 'item 3'];
for(var i = 0, str1 = ''; i < arr.length; i++) {
 str1 = str1 + ('<li>' + arr[i] + '</li>');
}
//<ul><li>item 1</li><li>item 2</li><li>item 3</li></ul>
document.write('<ul>' + str1 + '</ul>'); 

平均で2.9msですねー。抜いちゃったねー。ねー。ねー。

困ったな…。


それぞれ10回計測しましたが。


内容によりけりですよきっと。join関数使えば良いんじゃないでしょうか。なんとなくだけどjoin関数の速さは安定していた気がします。それにコード少なくて済むし。


8. グローバル変数を事業仕分け。レンホーさん「その変数がグローバルである必要は?」

グローバル変数を削減しましょうということです。原文からサンプルをもらいましょう。

バッドマンなコード。

var name = 'Jeffrey';
var lastName = 'Way';

function doSomething() {...}

console.log(name); // Jeffrey -- or window.name

グッドマンなコード。

var DudeNameSpace = {
   name : 'Jeffrey',
   lastName : 'Way',
   doSomething : function() {...}
}
console.log(DudeNameSpace.name); // Jeffrey

DudeNamSpaceオブジェクトのプロパティとして定義することにより、グローバル空間の予算を削減するわけでございます。

でもこれは、オブジェクトがよくわからない人にしてみればあれなので、パッと見て「うわなんじゃこりゃ」と思ったらスルーすれば良いのです。別に知らなくてもプログラムが組めないわけではないです。こういうことは、後から身につければ問題ないです。


9. コメント書かないとか中二までだしーキャハハハ

えーコメントかきましょうねというだけです。

// Cycle through array and echo out each name. 
for(var i = 0, len = array.length; i < len; i++) {
   console.log(array[i]);
}

一人で開発する分だったら、別にあってもなくてもいいと思いますよ。チームでやるんだったらつけるのが心配りでしょう。


10. JSがOffになっててもおれのハートはいつでもOnだぜ

原文の見出しは「Embrace Progressive Enhancement」です。

たぶんJSがoffになっててもサイトをしっかり利用できるようにしとけよ、ってことを文章で書いてるんじゃないかと思われる。

JSをoffにしているブラウザの方が近年では稀だけども、その人の環境がすごくひもじいときがあって、そういうときでも見えたら良いことですね。


11. SetIntervalやSetTimeOutの引数には関数使いましょう。私には募金しましょう

SetIntervalやSetTimeOutという関数がありまして、引数に入れた処理を一定時間実行し続けたり、経過した時間後にその処理を実行する、ということができたりします。そして、その引数には文字列を入れるなということです。それからお前に嫁はこないということです。

サンプルみてみましょう><

setInterval(
"document.getElementById('container').innerHTML += 'My new number: ' + i", 3000
);

文字列を引数に入れるのは良くないよーということですねー。ねー。効率が悪いらしい。じゃあどうすればいいかということで、たぶんこういうこと。

setInterval(
    function(){
      var dat = new Date();
      document.body.innerHTML = dat.toLocaleTimeString();
    },
    1000
  );

元のサンプルとは違ってローカルの時間を表示するというものです。firefoxのコンソールから実行できるかと。とりあえず引数に関数として入れればよいのです。ちなみに第2引数はミリ秒単位で第1引数の処理を実行する間隔を指定できます。この場合1秒ですね。


注意点として、たとえば別に名前をつけて関数定義したとき。

function func(){
  var dat = new Date();
  document.body.innerHTML = dat.toLocaleTimeString();
}

setInterval(func() ,1000);

これじゃだめです。こうです。

setInterval(func ,1000);

( )の関数を呼び出す演算子をつけないようにしましょう。なんでこれに違いがあるのかよくわからない人は、視覚的に見た方が早いです。

function func(){
  var dat = new Date();
  return dat.toLocaleTimeString();

}

// 23:40(PCの時間が表示されます)
alert(func());

// function func() { var dat = new Date; return dat.toLocaleTimeString(); }
alert(func); 

実行しているか、単に関数の内容を入れているかっていう違いですね。


setIntervalやsetTimeoutは結構よく使う関数なんで(たぶん)、なんとなくでもいいから今は覚えておきましょう。


12. with文とはもうこれっきりです。一緒(with)なのに一緒にいれない…クックック(笑)

さようなら><

一見、with文はとってもスマートなアイデアですね。サンプルをみてみましょう。

with (being.person.man.bodyparts) {
   arms = true;
   legs = true;
}

使ったことの無い人のために書くと、beingオブジェクトのpersonプロパティのmanプロパティのbodypartsプロパティのarmsプロパティとlegsプロパティに値を代入していることになります。よし意味分からんね!

つまり、

being.person.man.bodyparts.arms = true;
being.person.man.bodyparts.legs= true;

こういうことなんです。途中まで省略できちゃうねー。ねー。でもこれ使わない方が良いよーということみたいです。便利なんだけど、パフォーマンスの低下につながるのかな。というわけで、

var o = being.person.man.bodyparts;
o.arms = true;
o.legs= true;

この書き方がいいみたいです。with文については私もいくつか記事書いてるのでどうぞ。

http://d.hatena.ne.jp/sandai/20091104/p1

http://d.hatena.ne.jp/sandai/20091112/p1


13. new演算子でオブジェクトを生成するのは江頭に服を与えるようなものだ

オブジェクトを生成するときは、new演算子を使わずにオブジェクトリテラルを使って定義しましょうねー、ということなんです。

Don'tとは表現されていないので、まあ使っても良いけどリテラルの方がいいんじゃない?ということかと思います。

var o = new Object();
o.name = 'Jeffrey';
o.lastName = 'Way';
o.someFunction = function() {
   console.log(this.name);
}

new演算子を使ってオブジェクトを作ってます。でもこれは推奨でない。ではどうすればいいのかというと、

var o = {
   name: 'Jeffrey',
   lastName = 'Way',
   someFunction : function() {
      console.log(this.name);
   }
};

オブジェクトリテラルの波括弧を使いましょう、ということですね。ドット演算子を使ったバージョンと、使用例も。

var o = {};
o.name = 'Jeffrey';
o.lastName = 'Way';
o.someFunction = function() {
   console.log(this.name);
}

o.someFunction(); // jeffrey

firefoxのコンソールで実行してみてください。


オブジェクトがいまいちよーわからん、という初心者はこれもスルーでいいと思います。こういうのがあるんだなと記憶しておくぐらいが一番。後でできるようになればいいのです。


14. new演算子で配列を生成するのはエスパー伊藤にエスパー能力を与えるようなものだ

エレクトリカルパレード!イエス!

13. と似たようなことで、配列もnew演算子で生成しないほーがいいんじゃないぃ?ということです。

まあこれでもいいよ、というサンプル。

var a = new Array();
a[0] = "Joe";
a[1] = 'Plumber';

エレクトリカルパレードが流れるときのようなテンションでニコニコできるようなのが下記。

var a = ['Joe','Plumber'];

後者がベターなコードです。


関係ありませんが、配列ってlengthプロパティから増やすこともできるんですよー。

var arr = [];
arr.length = 10;
console.log(arr); 
// [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]

結構面白いでしょう。


15. 変数のvarなんて省略してカンマでつなげばいいのになんでやらないの?ねぇ?なんで?

原文からサンプルを。

var someItem = 'some string';
var anotherItem = 'another string';
var oneMoreItem = 'one more string';

ベターなコード。

var someItem = 'some string',
    anotherItem = 'another string',
    oneMoreItem = 'one more string';

でもたとえば、

var arrayVariable = [],
    objectVariable = {},
    stringVariable = '',
    intVariable = 0;

というのはどうなんでしょう?私は感覚的にわさわさするというか、気分が悪いからやりません。というか、型宣言するプログラミング言語だとこういうのはやりませんね。


16. 常に、常に、常にカンチョーの恐怖におびえていろ!ぐははっは

見出しの意味は見ただけでわかると思いますが、「常にセミコロンをつけなさいね」、ということです。

var s = 'わたしは、カンチョーを、しました。'
var f = function(){
 var ss = 'おかげで、べんぴがなおったそうです。'
 return s + ss
}
alert(f())

なんかすっごい見辛いし下品だ。セミコロンがないだけが理由だとは思わないけど、下品だ。

var s = 'わたしは、カンチョーを、しました。';
var f = function(){
 var ss = 'おかげで、べんぴがなおったそうです。';
 return s + ss;
};
alert(f());

こっちの方が見やすい。


for in文について

うーん、いまいちよくわからない。とりあえずのせてあったコード。

for(key in object) {
   if(object.hasOwnProperty(key)) {
      ...then do something...
   }
}

hasOwnPeroperty関数は、引数のプロパティ名がそのオブジェクトにあるかどうか調べることができる関数なんですが。これあまり意味がないんじゃないか。


原文をみると、

When looping through items in an object, you might find that you'll also retrieve method functions as well. In order to work around this, always wrap your code in an if statement which filters the information

関数も取得できちゃうから、それをはじくためにif文を使いましょうーね、と解釈したんですけど違うのでしょうか。


もうわからないので、for in文の不要なプロパティははじくというにしちゃいましょう。それで、たとえば関数以外のプロパティを調べたいときどうすればいいのかというもの。


普通に通すとこうなる。

var o = {a:1, b:2, c:3, d:4, e:5, f:function() { alert('f')}};
for(key in o) {
  document.write(o[key] + '<br />');
}
/*
1
2
3
4
5
function () { alert("f"); }
*/

こんな感じで関数まででひっついてくる。if文で関数を持っているプロパティははじきましょう。

var o = {a:1, b:2, c:3, d:4, e:5, f:function() { alert('f')}};
for(key in o) {
   if(!(typeof(o[key]) == 'function')) {
      document.write(o[key] + '<br />');
   }
}
/*
1
2
3
4
5
*/

はいよくできました☆

for in文では全てのプロパティを調べるので、if文とか使って不要なものははじかなくちゃならないのですねー。ねー。ここで初心者だとパッとみて、for in文がよくわからないかもしれない。

var o = {a:1, b:2, c:3, d:4, e:5, f:function() { alert('f')}};
var a = [];
var s = 0;
for(a[s++] in o);

document.write(a);
//a,b,c,d,e,f

for in文はオブジェクトのプロパティを順番に調べてるわけですありんす。これがたとえばfor文だったらできるかといえば、こうすんなりできませんね。ということで、for in文はオブジェクトに対して使うもので、配列だったらfor文をご利用になってください。


19. FirebugのTimerつかってますか?セコムしてますか?

コードの実行時間を計ることができます。Firebugのコンソール上に数値がでます。

function TimeTracker(){
 console.time("MyTimer");
 for(x=5000; x > 0; x--){}
 console.timeEnd("MyTimer");
}

console.time()とconsole.timeEnd()で、実行時間を計りたいコードをはさんでおくんなさい。便利ですよ。


20. 無駄無駄無駄無駄ッ!!!

正式なタイトルはRead, Read, Read...

つまり本読めということだそうで。あちらは洋書なので、日本語で個人的におすすめなのと評判良いののっけときます。


まず超初心者の本といえば、初めてのJavaScriptですね。はい、見たことがないんですけどね!ごめんね!

初めてのJavaScript 第2版 (大型本)
487311425X


個人的なおすすめとしてはこちら。ただし、オブジェクト指向は未経験者には大変難しい項目ですので、思いっきりおすすめできない。その他は分かりやすかったですよ。

JavaScriptマスターブック (単行本(ソフトカバー))
4839927081


それで、以上の2冊のどちらかを勉強したらこれ。文章ばっかりなので上の2つを通り越して読むのはおすすめできません。他のプログラミング経験者だったら大丈夫かもしれませんが、本当に初心者ならぜひ上の2冊のうちどちらかは読んでおきましょう。

JavaScript 第5版 (大型本)
4873113296


それからこれ。まだ買ったことがないのですが、良書と評判です。より良い技術が身につくのではないかなと。

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス (大型本)
4873113911


後はこちらもどぞ。

http://d.hatena.ne.jp/HolyGrail/20080713/1215974053


21. 自分の意思で生きるんだ!他人に左右されずに私は…ッ

英語の見出しはSelf-Executing Functionsと書かれています。えー、自分で実行する関数ってことですね。サンプルはこれ。

(function doSomething() {
   return {
      name: 'jeff',
      lastName: 'way'
   };
})();

なんて説明すればいいか。これを入門にもってくるかー。うーん、まずクロージャです。これクロージャです。…これ以上無理orz

これはビギナー向けじゃあないですよちくしょう。スルーしましょう。とりあえずクロージャについては検索してください。

javascript ?N???[?W?? - Google ????


クロージャはうまくつかいこなせないのでお手上げ。


22. JSキング「なぜJavaScriptライブラリを使わないかだって?当たり前だ。JavaScript図書館なんて意味わかんねーよ

そういう意味じゃないですキング><

JSのライブラリを使うよりも生のJSが速いのだそうです。Ajaxを利用する上でjQueryやprototype.jsは大変簡単で楽に使えますが、やっぱり生のJSにはかなわない。(正しいコードと仮定して)

jQueryのeachメソッドはグレイトだけど、普通のfor文の方が速いんだよーということらしい。実際に計測したことがないので私はわからないのですが。

何にしても勉強するんだったらまずは純粋なJSを勉強して、それからjQueryのソースコードとか眺めたりすると良いんじゃないかなと思います。


23. Crockford氏のJSON.Parse

JSONについてはこちら。

JSONってなにもの? | Think IT(シンクイット)


初心者向けではないよね。うーん。

JSONというデータ形式があって、XMLよりも扱いやすい。JSのオブジェクトや配列と同じような記述形式なんだけど、他の言語でも扱えるとのこと。PHPやRubyでも扱えるのではないかな。

それで、eval関数を使えば難なくJSのコードとして扱えるんだけど、その関数は非推奨というわけでJSON.parseを使いましょうねー、ということだと思います。

そしてこれを使うには、json2.jsというやつを使います。

http://www.json.org/json2.js

とりあえずサンプル。

var response = JSON.parse(xhr.responseText);

var container = document.getElementById('container');
for(var i = 0, len = response.length; i < len; i++) {
  container.innerHTML += '' + response[i].name + ' : ' + response[i].email + '
# ';
}

これはまたいずれ必要になったときに学習しようかと思います。ということでここは私もスルー。


24. ふははは!人がゴミのようだ!国なんて滅んでしまえ!

スクリプトタグのlanguage属性はもう使いません。私の国はもう、滅びたのです…。

//○
<script type="text/javascript"></script>

//×
<script type="text/javascript" language="javascript"></script>

これでいいのです。じゃあ、宇宙いきます。バルス。


終わり

外人はコメントでgreatとかniceとかamazingとか連発ですね。というかテンション高いなあ。いつもローなテンションなのでついていけない…ぜぁああッ!

stokiwastokiwa 2009/12/14 13:57 great!!

hinatahinata 2009/12/14 17:16 nice!!!11

passerbypasserby 2009/12/14 19:27 amazing!!!!!!!!!

gg 2009/12/14 20:15 great!!!!!!!!!!!!

unkounko 2009/12/14 21:08 yes!yes!

bb 2009/12/14 21:32 excellent;-)

sandaisandai 2009/12/14 23:11 Thanks everyone!However, the great Jeffrey! Not me.Thanks Jeffrey!
Still, difficult English...

yusukenakanishiyusukenakanishi 2009/12/15 01:35 Excellent!!!

gjgj 2009/12/15 11:08 great!

tyatya 2009/12/15 11:58 awesome!

r7kamurar7kamura 2009/12/15 17:07 nice code.

sandaisandai 2009/12/15 20:15 Thanks!Thanks!
I can't speak English anymore!

fmactionfmaction 2009/12/17 12:26 これは参考になりますね。

sandaisandai 2009/12/21 20:14 ありがとうございます。
日本語もありがとうございます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証