◆20200817 授業メモ スコープ・ドラクエの答え合わせ
本日の授業内容
〇スコープについて
変数の参照範囲のことを言う。
・グローバルスコープ
関数内・関数外で参照できる
・ローカルスコープ
関数内のみ参照できる
変数宣言の種類
1.無名
例)num1=100;
→グローバル変数。バグやエラーの原因になるので非推奨
2.var
宣言場所によってグローバル・ローカルになりうる
同盟変数の宣言はOK
3.let
宣言場所によってグローバル・ローカルになりうる
同盟変数の宣言はNG
ブロックスコープを持つ(宣言したブロック({}内)のみ使用可能)
4.const
定数の宣言:値の再代入ができない
読み取り専用変数
これも同盟変数の宣言はNG。
変数名を全て大文字にするという暗黙のルールがある
〇ローカルスコープ・ブロックスコープを用いた演習問題
以下板書
〇スコープとは
変数の参照範囲のことをいう
14章 global_scope1.jsより
例題
// 関数の定義
// 呼び出されたときに関数ブロック内を実行。
function test() {
console.log('関数内:' + num);
// グローバル変数は関数内からも参照可能
}
console.log('1回目の出力');
var num = 100;
// 関数外で宣言された変数は
// グローバルスコープを持つ
// グローバル変数として扱われる
console.log('関数外:' + num);
test();//引数なし戻り値なし関数の呼出し
// 変数宣言の種類(全4種)
// 宣言用のキーワードなし
// グローバル変数
num1 = 100;
// var
// 宣言場所によってグローバル変数・ローカル変数にもなり得る
var num2 = 200;
var num2 = 2000; //← 同盟変数の宣言おk。但しバグの温床になりがち
// うっかり違う値を管理する同盟変数を上書きしてしまうリスク。
// let
// 宣言場所によってグローバル変数・ローカル変数にもなり得る
// 同盟変数の宣言はNG。
// ブロックスコープを持つ
// 迷ったらletを使うとバグのリスクを減らせるかも。
let num3 = 300;
// const
// 定数の宣言:値の再代入ができない
// 読み取り専用変数
// これも同盟変数の宣言はNG。
// 変数名を全て大文字にする(推奨)
const num4 = 400;
// num4 = 4000; //←代入エラー
〇ローカルスコープ(ローカル変数)
宣言したブロック(大カッコ{ } )内でのみ利用可能
function test() {
var num = 100;//←{}内のみ使える変数
//ローカルスコープを持つローカル変数
//関数内でのみ使用可能
console.log('関数内:' + num);
}
console.log('1回目の出力');
test();//関数呼び出し
console.log('関数外:' + num);//←よってこの場合エラーになる。
例題
14章 function_scope2.jsより
function recoveryMagic(playerID, magicID) {
// var magicList = [
// { name: 'ホイム', point: 100 },
// { name: 'ベホイム', point: 200 },
// { name: 'ベホムズン', point: 300 },
// { name: 'メル', point: -20 },
// { name: 'メラム', point: -100 },
// { name: 'メルゾーマ', point: -300 },
// ];←ここに変数を宣言するとエラーになる。
console.log(playerList[playerID].name + 'は'
+ magicList[magicID].name + 'を唱えた!'
+ magicList[magicID].point + '回復');
return magicList[magicID].point;
}
function attackMagic(playerID, enemyID, magicID) {
// 使用する魔法情報をそれぞれ宣言して代入
// 魔法情報のIDが変わるので注意
console.log(playerList[playerID].name + 'は'
+ magicList[magicID].name + 'を唱えた!'
+ enemyList[enemyID].name + 'へ'
+ -magicList[magicID].point + 'のダメージ!');
return magicList[magicID].point;
}
var playerList = [
{ name: '田中', life: 1000 },
{ name: '佐藤', life: 500 },
];
var enemyList = [
{ name: 'スライム', life: 10 },
{ name: 'スライムキッド', life: 100 },
];
// 関数外で宣言されているのでグローバル変数
// 関数内から参照可能になる
var magicList = [
{ name: 'ホイム', point: 100 },
{ name: 'ベホイム', point: 200 },
{ name: 'ベホムズン', point: 300 },
{ name: 'メル', point: -20 },
{ name: 'メラム', point: -100 },
{ name: 'メルゾーマ', point: -300 },
];
console.log('1回目の出力');
playerList[0].life += recoveryMagic(0, 1);
console.log(playerList[0].life);
enemyList[1].life += attackMagic(1, 1, 3);
console.log(enemyList[1].life);
〇各スコープに同名変数
14章 w_scope1.jsより
function test() {
var num = 200;//ローカル変数宣言
console.log('関数内:' + num);
// ローカル変数が優先される
// 対象のローカル変数が存在しない場合、
// グローバル変数を参照しに行く
}
console.log('1回目の出力');
var num = 100;
test();
console.log('関数外:' + num);
〇ブロックスコープ
14章 block_scope.jsより
console.log('1回目の出力');
if (true) {
var num1 = 100;
// ブロック内で変数宣言
// varで宣言した場合はブロックスコープなし
console.log('ブロック内:' + num1);
}
console.log('ブロック外:' + num1);
// ブロックスコープなしなのでブロック外でも使用可能
// →よって{}外でも表示される
console.log('2回目の出力');
if (true) {
let num2 = 200;
// ブロック内で宣言
// letはブロックスコープありなので
// 宣言したブロック内({}内)のみで利用可能
console.log('ブロック内:' + num2);
}
console.log('ブロック外:' + num2);
// →よって{}外なのでエラー表示になる
let num2 = 300
// スコープ内にnum2が宣言されてなければ
// letで同盟変数を宣言できる
for (let i = 0; i < 5; i++) {
// for文の()内で宣言した変数は
// forブロック内で宣言した変数と同じになる。
console.log(i);
}
console.log(i);//←これはエラーになる。
// 変数iはブロックスコープを持っておるので
// for文外で使用することはできない。
console.log('検証3');
var time = 10;
if (time < 12) {
var message = 'おはよー';
} else if (time < 18) {
var message = 'こんにちは';
} else {
var message = 'こんばんみ';
}
console.log(message);
letで基本的に記述すること。
そうすることでエラーやバグの回避につながる
console.log('検証4');
console.log(num98)
let num98 = 100;
// letで宣言された変数は巻き上げ対象から外れる
〇const
14章 Constant.jsより
console.log('1回目の出力');
const NUM = 100;
console.log(NUM);
NUM = 200;//エラーになる
// 定数の値の再代入は不可
console.log(NUM);
// constで宣言すると定数
// 初回のみ代入可能で2回目以降は代入不可
// 暗黙のルール:変数名は全て大文字
// 値の変更がない場合は全て定数が望ましい
〇未宣言変数
14章 undeclared.jsより
function test() {
num = 100;
// ↑キーワードなしの変数はグローバル変数
console.log('関数内:' + num);
}
// 関数内で作成した未宣言変数はグローバル変数として扱う
// 故に関数外で利用することが可能
console.log('1回目の出力');
test();
console.log('関数外:' + num);
// バグやエラーの原因になりやすいのであまり使用はおすすめしない
※for文で使われるiについて
for (i = 0; i < 5; i++);
カウント変数が未宣言変数
関数外でiが使えるようになってしまう