Miyazaki.js vol.1 スコープの話

Preview:

DESCRIPTION

2014/10/18 Miyazaki.js vol.1 スコープの話

Citation preview

スコープの話

自己紹介

Nobuhiro Nakashima @ombran JavaScript/Ruby/サンホラ/アニオタ 株式会社アラタナ エンジニア Miyazaki.js主催

スコープ

– by Wikipedia

“ある変数や関数が

特定の名前で参照される範囲のこと”

スコープ

スコープの種類

global scope プログラム「全体」から見えるスコープ

file scope プログラムを記述したファイルの内側でのみ参照できるスコープ

local scope ある関数やブロックの範囲内に限定されたスコープ

instance scope いわゆるカプセル化

class scope あるクラスの定義全体から参照できるスコープ

global scope プログラム「全体」から見えるスコープ

file scope プログラムを記述したファイルの内側でのみ参照できるスコープ

local scope ある関数やブロックの範囲内に限定されたスコープ

instance scope いわゆるカプセル化

class scope あるクラスの定義全体から参照できるスコープ

JavaScript

でのスコープ

スコープの例

var scope = "Global";

function getValue() { console.log(scope); // > undefined var scope = "Local"; return scope; }

console.log(getValue()); // > "Local" (ローカル変数を参照)

console.log(scope); // > "Global" (グローバル変数を参照)

var scope = "Global";

function getValue() { console.log(scope); // > undefined var scope = "Local"; return scope; }

console.log(getValue()); // > "Local" (ローカル変数を参照)

console.log(scope); // > "Global" (グローバル変数を参照)

global scope

var scope = "Global";

function getValue() { console.log(scope); // > undefined var scope = "Local"; return scope; }

console.log(getValue()); // > "Local" (ローカル変数を参照)

console.log(scope); // > "Global" (グローバル変数を参照)

local scope

スコープの話の前に 変数の前のやつを説明します

varについて

varなし→必ずグローバル

varあり→スコープ内変数

varは絶対付けること

スコープをもうちょっと深く

global scope

• functionの外で宣言された変数・関数

• varなしで宣言された変数

var scope = "Global";

function getValue() { console.log(scope); // > “Global” scope = "Global2"; return scope; }

console.log(getValue()); // > "Global2" console.log(scope); // > "Global2"

functionの外で宣言

function getValue() { scope = "Global2"; return scope; }

console.log(getValue()); // > "Global2" console.log(scope); // > "Global2"

varなしで宣言

local scope

• functionの中で宣言された変数・関数

• functionの引数で宣言された変数

var scope = "Global";

function getValue() { console.log(scope); // > undefined var scope = "Local"; return scope; }

console.log(getValue()); // > "Local" console.log(scope); // > "Global"

functionの中で宣言

var scope = "Global";

function getValue(arg1) { console.log(arg1); // > “Global” arg1 = "Local"; return arg1; }

console.log(getValue(scope)); // > "Local" console.log(scope); // > "Global"

functionの引数で宣言

なぜこういう挙動をするのか

スコープチェーン

var a = “GlobalA”; var b = “GlobalB”;

function func1() { var b = “Func1B”;

function func2() { var c = “Func2C”;

console.log(c); // > “Func2C” console.log(b); // > “Func1B” console.log(a); // > “GlobalA” } func2(); } func1();

ここの変数の値を探すルール

var a = “GlobalA”; var b = “GlobalB”;

function func1() { var b = “Func1B”;

function func2() { var c = “Func2C”;

console.log(c); // > “Func2C” console.log(b); // > “Func1B” console.log(a); // > “GlobalA” } func2(); } func1();

Cはこのスコープで見つかる

var a = “GlobalA”; var b = “GlobalB”;

function func1() { var b = “Func1B”;

function func2() { var c = “Func2C”;

console.log(c); // > “Func2C” console.log(b); // > “Func1B” console.log(a); // > “GlobalA” } func2(); } func1();

Bはこのスコープで見つかる

var a = “GlobalA”; var b = “GlobalB”;

function func1() { var b = “Func1B”;

function func2() { var c = “Func2C”;

console.log(c); // > “Func2C” console.log(b); // > “Func1B” console.log(a); // > “GlobalA” } func2(); } func1();

Aはこのスコープで見つかる

var a = “GlobalA”; var b = “GlobalB”;

function func1() { var b = “Func1B”;

function func2() { var c = “Func2C”;

console.log(c); // > “Func2C” console.log(b); // > “Func1B” console.log(a); // > “GlobalA” } func2(); } func1();

変数の 検索範囲が徐々に広がっている

これが スコープチェーン

var scope = "Global";

function getValue() { console.log(scope); var scope = "Local"; return scope; }

console.log(getValue()); // > "Local" console.log(scope); // > "Global"

さっきのやつ

この時点で同一スコープを探す

var scope = "Global";

function getValue() { console.log(scope); var scope = "Local"; return scope; }

console.log(getValue()); // > "Local" console.log(scope); // > "Global"

さっきのやつ

この時点で同一スコープを探す

いた!!

なぜundefined?

var scope = "Global";

function getValue() { var scope; console.log(scope); // > undefined scope = "Local"; return scope; }

console.log(getValue()); // > "Local" console.log(scope); // > "Global"

こういうイメージ

だから変数は最初に 全部書きましょう

スコープチェーン による強力な機能

の前に ちょっと最新の話

ちなみに Javaなどにある

ブロックスコープですが

var sum = 0;

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

console.log(sum); console.log(i);

ブロックスコープ

var sum = 0;

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

console.log(sum); // > 45 console.log(i); // > ??

ブロックスコープ

var sum = 0;

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

console.log(sum); // > 45 console.log(i); // > ReferenceError 10

ブロックスコープ

var sum = 0;

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

console.log(sum); // > 45 console.log(i); // > ReferenceError 10

ブロックスコープ

ECMAScript6の新機能

letでできるよ

var sum = 0;

for (let i = 0; i < 10; i++) { sum += i; }

console.log(sum); // > 45 console.log(i); // > ReferenceError

ブロックスコープ

戻ります

スコープチェーン による強力な機能

クロージャ

– by Wikipedia

“引数以外の変数を実行時の環境ではなく、 自身が定義された環境(静的スコープ)において解決することを特徴とする。”

クロージャ

var a = “GlobalA”; var b = “GlobalB”;

function func1() { var b = “Func1B”;

function func2() { var c = “Func2C”;

console.log(c); // > “Func2C” console.log(b); // > “Func1B” console.log(a); // > “GlobalA” } func2(); } func1();

さっきのも クロージャ

クロージャの 実践例

function counter() { var count = 0;

return function() { count = count + 1; return count; } }

var cnt = counter(); console.log(cnt()); // > 1 console.log(cnt()); // > 2 console.log(cnt()); // > 3

変数の 永続化

function counter() { var count = 0;

return function() { count = count + 1; return count; } }

var cnt = counter(); console.log(cnt()); // > 1 console.log(cnt()); // > 2 console.log(cnt()); // > 3

変数の 永続化

ここで変数が束縛される

function counter() { var count = 0;

return function() { count = count + 1; return count; } }

var cnt = counter(); console.log(cnt()); // > 1 console.log(cnt()); // > 2 console.log(cnt()); // > 3

変数の 永続化

束縛されたままなので 値がインクリメントされる

即時関数

function helloWorld() { alert("Hello, World!"); } helloWorld();

普通の関数定義と実行

(function helloWorld() { alert("Hello, World!"); })();

即時関数

定義後、即実行

メリット

グローバルスコープを 汚さない

(function helloWorld() { alert("Hello, World!"); })();

helloWorld(); // > エラー

即時関数

ということは 関数名もいらない

(function() { alert("Hello, World!"); })();

即時関数

無名関数

どういう時に使うか

(function() { var hoge = 1; function fuga() { console.log(hoge); } fuga(); })();

ファイル内の全コードを囲む

なにがうれしい?

グローバルスコープを 汚さない

同一ページで 複数JSファイルを 読み込んでも

他のJSを壊さない

(function() { // ここに自分の

//JavaScriptコードを書く

})();

(function() { // ここに自分の

//JavaScriptコードを書く

})();

マナーとして覚えてください

fin

Recommended