Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
覚醒!JavaScript
株式会社 gumi 原口 剛
自己紹介
• 原口 剛 (はらぐち ごう)
• フロントエンドエンジニア
• 2012年 gumi入社
• スマホWebゲーム
黒歴史
•28歳でJavaでHelloWorld!を書く
•受託システム開発

Java+ActionScript3
•ソシャゲ開発

ケータイFlash制作
•スマホ対応で初めてHTML+CSSを書く

JavaScriptほとんど書いてない
•某価格比較サイトのコーダー業務

スマホ版のカルーセルUI実装で初めて
本格的にJavaScriptにちゃんと触れる
が、しかし!!
それは、”jQueryJavaScript”だった・・・
$('.carousel-prev').click(function () {
$('.carousel').carousel('scroll', '-=1');
});
$('.carousel-next').click(function () {
$('.carousel').carousel('scroll', '+=1');
});
(勝手に命名)
jQueryじゃダメなの!?
小規模ならいいかもね
中・大規模だと破綻するかもね
なんでjQueryじゃダメなの!?
ネームスペースの問題・ハンドラ関数の爆発的増加・
コード再利用のやりづらさetc
と、その話はおいといて・・・
模範的なJavaScriptプロジェクト
プログラミング上達のコツは?
教わるよりも学びましょう!
守・破・離
模範的なJavaScriptプロジェクト
jQuery, Underscore.js, Knockout.js等々
著名なライブラリやフレームワークの中身を
理解可能なレベルになっておきたい!
そこから学べる要素が必ずあるはずです!
理解できるレベルとは?
• なんとなくではなく、明確に理解している
• ブラックボックス症候群にはご注意を!
アジェンダ
•JavaScriptオブジェクト
•関数(Function())
•グローバルオブジェクト
•this
•スコープとクロージャ
JavaScriptオブジェクト
JavaScriptオブジェクト
JavaScriptの世界では、

ほぼすべてがオブジェクトそのものか、

もしくはオブジェクトのようにふるまう
オブジェクト
『名前』と『値』を持つプロパティを

格納するコンテナ
var man = new Object();
man.living = true;
man.age = 35;
man.gender = 'male'; 値
名前
メソッド
単なるデータのみだと、オブジェクトはJSONのよ
うなデータベースすぎないが、オブジェクトには
ふるまいを付与できる
メソッド
var man = new Object();
man.living = true;
man.age = 35;
man.gender = ‘male';
man.getGender = function(){
return man.gender;
}
ふるまい
コンストラクタ関数
一見、普通の関数
一般的に関数名の先頭文字を大文字にしている
new演算子を伴って呼び出された場合、コンスト
ラクタ関数は特別な役割をする
特別な役割?
本来return文を宣言しない場合にはfalse相当の値を
返すところ、コンストラクタ関数は代わりに新た
に生成されるオブジェクトを返す
コンストラクタ関数中のthisは、戻り値であるオブ
ジェクトを示す予約語
var Person = function (living, age, gender) {
this.living = living;
this.age = age;
this.gender = gender;
this.getGender = function () {
return this.gender;
};
};
var haraguchi_10 = new Person(true, 10, ‘male’);
var haraguchi_20 = new Person(true, 20, ‘male’);
var haraguchi_30 = new Person(true, 30, ‘male');
コンストラクタ関数
ネイティブコンストラクタ
JavaScriptには、9つのネイティブオブジェクトコン
ストラクタが存在する
JavaScriptのさまざまな機能を整えるためにも使用さ
れる
関数は、Function()コンストラクタから生成されるオ
ブジェクトで、new演算子とともに使用することで、
コンストラクタとして他のオブジェクトを生成する
9つのオブジェクト
Number() 、String()、 Boolean()、 Object()、 Array()
Function()、 Date()、 RegExp()、 Error()
言語の深層部を理解するには、以上のネイティブ
オブジェクトコンストラクタ関数を知っておくこ
とが になる
リテラル
オブジェクト生成のショートカット
リテラルはnew演算子が行うことを隠 しているにすぎない
オブジェクトの生成はリテラルの方がお手軽だし便利
var myNumber = new Number(10000);
var myNumberLiteral = 10000;
console.log(myNumber.constructor, myNumberLiteral.constructor);
Number() Number()
newする
リテラル
プリミティブ値
null, undefiend, ’string’, 10, true, falseなどは

オブジェクトではなくプリミティブ型
一部のプリミティブ型はオブジェクトのように扱
うとオブジェクトのようにふるまう
var name= “Haraguchi”;
console.log(name.toString()); オブジェクト型化
オブジェクトの保持
• オブジェクトは参照によって保存・操作される
• 変数名からメモリ上のアドレスにアクセスする
• 変数に代入すると参照(アドレス)がコピーされる
• 参照先の変更は、同じ参照をしている変数全てに
かかる
var myObject = {};
var copyOfMyObject = myObject;
myObject.foo = 'bar';
console.log(myObject, copyOfMyObject); // 出力:
参照をコピー
同じ参照 同じ参照
オブジェクトの同値判定
• 同じ参照のときに同値
• 値が同じでも、参照が異なれば同値ではない
var objectFoo = { same: 'same' };
var objectBar = { same: 'same' };
console.log(objectFoo === objectBar);
!
!
別参照
別参照
出力: false
関数
関数(Function())
一般的にはfunction演算子(関数リテラル)を使う
方法で生成する
var addNumber = function(num1, num2){
return num1 + num2};
console.log(addNumber(2, 3));
関数について
• 関数は常に値を返す

return文を記述していない場合などはundefinedが返
される
• JavaScriptの関数は「値」として格納できる特徴が
る( 第1級関数)
• 関数もオブジェクト
関数の実行方法
• 関数として実行
• メソッドとして実行
• コンストラクタとして実行
• apply()もしくはcall()を使って実行
new Hoge()
foo.hoge()
hoge()
apply()
var myObject = {};
var myFunction = function (param1, param2) {
this.foo = param1;
this.bar = param2;
console.log(this)
};
myFunction.apply(myObject, ['foo', 'bar']);
console.log(myObject);
配列
apply()
var myObject = {
myFunction: function (param1, param2) {
this.foo = param1;
this.bar = param2;
console.log(this)
}
};
myObject.myFunction('foo', 'bar');
console.log(myObject);
call()
var myObject = {};
var myFunction = function (param1, param2) {
this.foo = param1;
this.bar = param2;
console.log(this)
};
myFunction.call(myObject, 'foo', 'bar');
console.log(myObject);
第二引数以降
call()
var myObject = {
myFunction: function (param1, param2) {
this.foo = param1;
this.bar = param2;
console.log(this)
}
};
myObject.myFunction('foo', 'bar');
console.log(myObject);
関数の即時実行
関数式は関数定義の後に()演算子を付与するこ
とによってその場で実行する。
(function(msg){
console.log(msg)
})(“Hello”);
再帰
• 関数は自分自身を呼び出すことができる
• 再帰の繰り返しは一般的なコーディングパターン
var countdown = function countdown(num) {
console.log(num);
num--;
if (num < 0) {
return false;
}
countdown(num);
};
countdown(5);
再帰
中断
グローバルオブジェクト
グローバルオブジェクト
Webブラウザ環境だとwindowオブジェクト
グローバルオブジェクト直下に格納されているの
が、グローバルプロパティ、グローバル変数
JavaScriptはあらかじめ定義されている関数を幾つ
か持っていて、これをグローバル関数と呼ぶ
グローバル関数
decodeURI(encodedURI),
decodeURIComponent(encodedURIComponent),
encodeURI(uri), encodeURIComponent(uriComponent),
eval(x), isFinite(number), isNaN(number),
parseFloat(string), parseInt(string, radix)
グローバル変数の作り方
グローバルスコープ下でvar演算子を伴って変数を宣言す
る場合、その変数はグローバル変数となる。
var演算子を使用しない場合はグローバルプロパティとし
て宣言される。
違いとしてはdelete演算子で消せるかどうか。
delete演算子はオブジェクトプロパティを削除する唯一
の手段。
var a = 10;
b = 100;
delete a;
delete b;
グローバル変数
グローバルプロパティ
削除できない
削除できる
this
this
関数が実行される際、thisキーワードの値が設定さ
れる。このとき設定される値は、関数を呼び出す
オブジェクトへリンク
var man = {
name: “Haraguchi”,
getName: function(){return this.name};
};
manを示す
thisの値はどのように決まる?
• 全ての関数に渡されるthisの値は、関数が実行時に
呼び出される際のコンテクストに依存する。
• JavaScriptの「癖」のひとつ
var foo = 'foo';
var myObject = { foo: 'I am myObject.foo' };
var sayFoo = function () {
console.log(this['foo']);
};
myObject.sayFoo = sayFoo;
myObject.sayFoo();
sayFoo();
プロパティに関数指定する
オブジェクトメソッド実行
関数実行
入れ子関数内でのthis
入れ子関数内では、thisはグローバルオブジェクト
を参照するという完全に方向を誤った仕様。
var myObject = {
func1: function () {
console.log(this);
var func2 = function () {
console.log(this) ;
var func3 = function () {
console.log(this);
}();
}();
}
}
myObject
window
window
入れ子関数内でのthisの保持
入れ子関数内でのthisの値見失わないために、一般
的に入れ子関数からアクセスできるスコープに
var self = thisなどで保持して、そのselfを使用する
ことでthisを見失うことがない
var myObject = {
myProperty: 'I can see the light',
myMethod: function () {
var self= this;
var helperFunction = function () {
console.log(self.myProperty);
console.log(this);
};
helperFunction();
}
}
myObject.myMethod();
window
myObject
thisを保持
スコープとクロージャ
スコープとクロージャ
コードが実行されるコンテクストにスコープが割
り当てられる。スコープには、下記の三つのタイ
プがある。
• グローバルスコープ
• ローカルスコープ(関数スコープ)
• evalスコープ(非推奨)
スコープ別出力例
var foo = o;
console.log(foo);
var myFunction = function(){
var foo = 1;
console.log(foo);
}
eval(‘var foo = 3; console.log(foo);’);
グローバルスコープ
ローカルスコープ
evalスコープ
ブロックスコープは無い
var foo = 1;
if (true) {
foo = 2;
foo = i;
console.log(foo);
}
fooの値が書き換わる
同じスコープ
同じスコープ
スコープチェーン
変数を参照する時、近いローカルスコープから探し、見つからな
かったらグローバルスコープまで る
var x = 10;
var foo = function () {
var y = 20;
var bar = function () {
var z = 30;
console.log(z + y + x);
};
};
foo();
「bar」のローカルスコープ
「foo」のローカルスコープ
グローバルスコープ
静的スコープ
• 関数定義時の場所にもとづいてスコープが決定
• thisの決定(実行時)とは、違う
• 定義済みの関数を別スコープへ渡しても、スコー
プチェーンは変わらない
var parentFunction = function () {
var foo = 'foo';
return function () {
console.log(foo);
}
}
var nestedFunction = parentFunction();
nestedFunction(); 出力: 'foo'
無名関数を参照
出力: 'foo'
クロージャ
クロージャを一言で表すと「スコープチェーンに
よって存在する変数への参照を保持している関数」
• カプセル化
• グローバル変数汚染を防ぐ
カプセル化
var countUp = function () {
var count = 0;
return function () {
return ++count;
};
}();
console.log(countUp());
console.log(countUp());
console.log(countUp());
子関数からのみアクセス可能
スコープチェーンをだとる
スコープチェーンをだとる
スコープチェーンをだとる
クロージャ失敗例
var foo = function () {
var funcArray = [];
var i;
for (i = 0; i < 3; i++) {
funcArray[i] = function () {
console.log(i);
};
}
return funcArray;
}();
foo[0].();
foo[1].();
子関数からは共通のiにアクセス
関数の参照を保持
クロージャ成功例
var foo = function () {
var funcArray = [];
var i;
var func = function (i) {
return function () {
console.log(i);
};
}
for (i = 0; i < 3; i++) {
funcArray[i] = func(i);
}
return funcArray;
}();
独自に持つローカル変数変数
クロージャを配列に格納
配列に格納された関数を実行
funcArray[0]();
funcArray[1]();
funcArray[2]();
出力: 0
出力: 1
出力: 2
まだまだいろいろありますが、
所 は、枝葉の知識。
Cody Lindley 著、和田 祐一郎 訳
開眼!
JavaScript――
言語仕様から学ぶ
JavaScriptの本
質
fin.
ご静聴ありがとうございました。

More Related Content

覚醒!JavaScript