Upload
osamu-monoe
View
35.661
Download
2
Embed Size (px)
Citation preview
モテる JavaScript
日本マイクロソフト株式会社デベロッパー & プ ラットフォーム統括本部物江修Twitter : osamum_MS
Blog : http://blogs.msdn.com/b/osamum/
目的
• 他人に見られて恥ずかしくないコードを書く
• 格好良い JavaScript コードを書いてモテる
アジェンダ
•知っておきたい JavaScript の慣例的な記述方法とマナー
•使われているとなんかカッコ良い JavaScript の機能
•最近、こんなふうに書いてます。
知っておきたい JavaScript の慣例的な記述方法とマナー
変数 / 関数の命名規則•基本
var fistName; ( キャメルケース )
•コンストラクタ var calendar = new CalenderCtrl(); (先頭が大文字 )
• this ( 現在の名前空間 )var that = this;
•定数var GENERAL_API_KEY = "4fh5cv$sp";
• プライベート var _userName = "user01";
変数 / 関数を判別する工夫
•関数 : 動詞を先頭ex) setHandler, getInfo, loadContent
•変数 : 単語間を _ ( アンダースコア ) でex) var first_name = "";
変数を宣言する場所
•関数の先頭•すべての変数
function myFunc(){ var shopName; var address; var phone; var catchCopy; ・ ・
function myFunc(){ var shopName, address, phone, catchCopy; ・ ・
スコープ (1/2)• JavaScript の変数スコープは関数単位
// 変数 i と fullName のスコープは for 文内に閉じていないfor (var i = 0; i < length; i++) { var fullName = items[i].firstName + " " items[i].lastName; :// 以下は期待どおりの動作とならないfor (var i=0; i<5; i++) { console.log("Outer loop " + i); for (var i=0; i<10; i++) { console.log("Inner loop " + i); }}
•宣言されていない変数は巻き上げられる•複数回宣言可能 ( 上書きれる )
スコープ (2/2)
function myFunc(){ $ = "Hello";//jQuery を使用していた場合、正常に動作しなくなる 意図しない名前空間の変数書き換え⇒ 名前空間の汚染
名前空間を汚染しないための工夫• “use strict” の使用•即時実行関数に閉じる
<script>(function(){"use strict"; onload = function(){ var variable1, variable2, variable3; // ページ読み込み時の処理 }; function otherFunction(){ // 関数の処理 };})();</script>
オブジェクトを利用した書き方 (1)var myUtil = { methodA : function () { //method A の処理 return resultValue; }, methodB : function(arg){ //method B の処理 return resultValue; }};// 呼び出し方var variable = myUtil.methodA();
オブジェクトを利用した書き方 (2)var myUtil = {};myUtil.methodA = function () { //method A の処理 return resultValue; };myUtil.methodB = function (arg) { //method B の処理 return resultValue; };
// 呼び出し方は同じvar variable = myUtil.methodA();
中括弧 ({}) の書き方 (1/2)
•中括弧の開始タグの前で改行しない• 暗黙的 ; ( セミコロン ) の挿入による意図
しない動作となる場合がある
function userInfo(){ return { firstName : " ひろし", lastName : " 山田 ", age : 23};}
×〇
function userInfo(){ return { firstName : " ひろし", lastName : " 山田 ", age : 23};}エラーが発生
中括弧 ({}) の書き方 (2/2)
• if 文は {} を省略せずに書く
if( itemslength == MAX_LENGTH) countLabel.innerText = "Full"; else countLabel.innerText = itemslength;
if( itemslength == MAX_LENGTH) { countLabel.innerText = "Full"; }else{ countLabel.innerText = itemslength;}
△
〇
DOM アクセスについて
• DOM ツリーを探すのでアクセスにはコストがかかる• 2 回以上アクセスする際はインスタンスを変数に
// 一般的に使用される DOM エレメントのインスタンスの取得法var element = document.getElementById(" エレメントのID"); .getElementByName(" エレメントの名前 "); .querySelector("CSS セレクタ "); .activeElement(); .all();
DOM アクセスの例// 非常に効率が悪い例for(var i=0; i < document.getElementById(“itemList”).childNodes.length; i++){ document.getElementById("itemList").childNodes[i].innerText = " アイテム " + i;}
// ロスを減らした例var nodes = document.getElementById("itemList").childNodes;var length = nodes.length;for(var i=0; i< length; i++){ nodes[i].innerText = " アイテム " + i;}
ここまでのまとめ
•慣例的な記述方法•可読性を高めるため•メンテナンス性を高めるため•意図しない動作を避けるため•他者に迷惑をかけないためのマナー
使われているとなんかカッコ良い JavaScript の機能
あいまいな評価の利用 (1/3)
• JavaScript の 5 つの false
以下はいずれも false と判断される
falsenullundefined"" ( 空文字 )0NaN (not a number)
if(stringData!="") ⇒ if(stringData)
あいまいな評価の利用 (2/3)
いろいろな使いみち
if(myObject) // オブジェクトのインスタンスの有無if(document.addEventListener) // メソッドの有無if(items.length) // 要素の有無 ( 数 )
定義済み判定のさらに短い書式
// 変数の初期値設定function(stringArg){ stringArg = stringArg || "defaultValue";
// 安全な名前空間の登録var myApp = myApp||{};
•注意が必要な場合も
あいまいな評価 (3/3)
以下の式は正しく評価されないconsole.log(0 == ''); //trueconsole.log(0 == '0'); //trueconsole.log(false == '0'); //trueconsole.log(null == undefined); //trueconsole.log(0 == '\t\r\n'); //true
あいまいな評価を避けるには
===!==
•厳密な評価が可能
イコール
Not イコール
console.log(null === undefined); //false
即時実行関数• (function(){// 処理 })();• 一か所からのみ呼び出される• 名前空間を使用しない
var shopName = item.shopName;var avgFare = item.avgFare;var creditCard = (function(sepChar){ var dotList = "", cardList = item.creditCardList, length = cardList.length; for(var i=0; i<= length; i++){ dotList += cardList[i].name + sepChar; } return dotList;
})(",");
クロージャー (1/3)•渡された引数の値を保持する
function makeAdder(x){ return function(y){ return x + y; }}
var add5 = makeAdder(5);var add10 = makeAdder(10);
console.log(add5(2)); //7 console.log(add10(2)); //12
クロージャー (2/3)
[[scoope]]makeAddr
add5
add10
function(y){return x + y}[[scoope]]
function(y){return x + y}[[scoope]]
[[scoope]]x : 10
[[scoope]]x : 5
function (x){ return function( y ) { ・・・ } }
クロージャー (2/3)
var ctrl_listView = document.getElementById("itemList"), ctrl_item = null; for(var i=0; i <=5; i++){ crtl_item = document.createElement("li"); crtl_item.innerText = " リンク " + i; crtl_item.addEventListener("click", function (index) { return function(){
console.log(index + " 番目がクリックされました。 ");
} }(i) , false); ctrl_listView.appendChild(crtl_item); }
• ex) リストに生成時のインデックスを保持
メソッドチェーン (1/2)
• ワンライナー ( 一行 ) で複数メソッドの呼び出し• オブジェクトツリーの検索処理の軽減
01| myPage.setCtrl();02| myPage.setHendler();03| myPage.loadData();
01| myPage.setCtrl().setHendler().loadData();
メソッドチェーン (2/2)var myPage = { methodOne : function(){
console.log("ONE"); return this;},
methodTwo : function(){ console.log("TWO"); return this;},
methodThree : function(){ console.log("THREE");
return this;}
}
// 呼び出しmyPage.methodOne().methodTwo().methodThree();
ここまでのまとめ
• JavaScript の良い意味での「曖昧さ」を理解してうまく使うことでコンパクトで効率の良いコードが書ける•関数の実行タイミング、メモリの使われ方をすることで頓智の効いたコードが書ける
最近、こんなふうに書いてます。
完結したページ / コントロールを 1 対 1 のオブジェクトで管理
var thisPage ={ ctrls:{
// コントロールの// インスタンスを保持
}, init:{
// ページの初期化関数群 }, handlers:{
// イベントハンドラ群 }, util:{
// 一般関数群 }}
初期化オブジェクトの中身var thisPage ={ ctrls:{ listBox:null }, init:{ setCtrls:function(){ this.ctrl.listBox = id$("listBox"); return this; }, setHandlers:function(){
this.ctrl.listBox.addEventListener("change",this.hendlers.changeItem,false);
return this; }, lenderPage:function(){ //listBox へのデータロード処理等 return this;
} }
初期化メソッドの呼び方
onload = function(){
thisPage.init.setCtrls().setHandlers().lenderPage();
}// 正常時、エラー時に実行する関数を引数に.lenderPage(success,error);
Web ページの場合の応用・ブラウザ間のイベント設定の記述の違いを吸収するvar util ={ addEvent:null, init: function () { if(document.addEventListener) { this.addEvent = function(element, type, handler){ element.addEventListener(type, handler, false); } }else if(document.attachEvent) { this.addEvent = function(element, type, handler){ element.attachEvent('on' + type, handler); }}}}
// 初期化util.init();// イベントハンドラの設定util.addEvent(document.getElementById("button"));
ここまでのまとめ
•インタラクティブに動作する Web アプリケーションは、ページをオブジェクトを介して抽象化すると扱いやすい
まとめ
•日々是学び•「オトコならシャツ一枚にもこだわれ」⇒「技術者ならコード一行にこだわれ」
enjoy!
参考
O’RELLY Japan JavaScript
http://www.oreilly.co.jp/books/9784873113296/
参考O’RELLY Japan JavaScript: The Good Parts―― 「良いパーツ」によるベストプラクティス http://www.oreilly.co.jp/books/9784873113913/
参考O’RELLY Japan JavaScript パターン――優れたアプリケーションのための作法
http://www.oreilly.co.jp/books/9784873114880/
© 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.
The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information
provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.