見出し画像

HTML5レベル2 勉強メモ: JavaScript




識別子

認められる識別子:

最初の文字は、アルファベットの文字(大文字または小文字)、アンダースコア (_)、またはドル記号 ($) でなければなりません。
2文字目以降は、数字も使用できます。
Unicode文字も使用できます。

let _variable;
let $variable;
let variable1;
let あいうえお; // Unicode characters

認められない識別子:

数字から始まる識別子は許可されていません。
空白や特殊文字(例えば、%, #, @)を含む識別子は許可されていません。
JavaScriptの予約語(例えば、function, for, ifなど)は識別子として使用できません。

let 1variable; // Invalid, starts with a number
let variable-name; // Invalid, contains a special character
let function; // Invalid, uses a reserved word

JavaScriptの動的型付けの例を書いて

let variable = "Hello, World!"; // variable is a string
console.log(typeof variable); // Outputs: string

variable = 42; // variable is now a number
console.log(typeof variable); // Outputs: number

variable = true; // variable is now a boolean
console.log(typeof variable); // Outputs: boolean

プリミティブ型:

Number: 数値を表す。例: let age = 25;
String: 文字列を表す。例: let name = "John";
Boolean: 真偽値を表す。例: let isApproved = true;
Null: 値が存在しないことを表す。例: let car = null;
Undefined: 値が未定義であることを表す。例: let test;
Symbol: ES6で導入された、一意で不変の値を表す。例: let sym = Symbol();
BigInt: 非常に大きな整数値を表す。例: let bigInt = 123n;

let num = 10; // Number
let str = "Hello"; // String
let bool = true; // Boolean
let nothing = null; // Null
let notDefined; // Undefined
let symbol = Symbol("id"); // Symbol
let bigInt = 123n; // BigInt

オブジェクト型:

Object: キーと値のペアの集合を表す。例: let student = {firstName: "John", lastName: "Doe"};
Array: 順序付けられた要素の集合を表す。例: let numbers = [1, 2, 3, 4, 5];
Function: 実行可能なコードブロックを表す。例: let greet = function() { console.log("Hello, World!"); };
Date, RegExp, Map, Setなどの他のビルトインオブジェクトもあります。

let obj = {name: "John", age: 30}; // Object
let arr = [1, 2, 3, 4, 5]; // Array
let func = function() { console.log("Hello, World!"); }; // Function
let date = new Date(); // Date
let regex = /ab+c/; // RegExp
let map = new Map(); // Map
let set = new Set(); // Set

配列はオブジェクト型

代入するとアドレス値がコピーされる

なのでarray1の値を買い替えればarray2の値も変わる

var array1 = [1, 2, 3, 4, 5];
var array2 = array1;
array1[2] = 10;
for (var data of array2) {
    console.log(data);
}



let obj1 = { value: 'original' };
let obj2 = obj1;

obj2.value = 'changed';

console.log(obj1.value); // Outputs: 'changed'
console.log(obj2.value); // Outputs: 'changed

オブジェクト型の比較

オブジェクト型はアドレス値を見る

var num1 = new Number(100);
var num2 = new Number(100);
var str1 = new String("100");
var str2 = new String("100");

console.log(num1 == num2); // 参照先が違うのでfalse
console.log(num1 == str1); // 参照先が違うのでfalse
console.log(str1 == str2); // 参照先が違うのでfalse

console.log(num1 == 100); // true
console.log(str1 == 100); // true

プリミティブ型の比較

var num1 = 100;
var num2 = 100;
var str1 = "100";
var str2 = "100";

以下は全てtrue

console.log(num1 == num2);
console.log(num1 == str1);
console.log(str1 == str2);
console.log(num1 == 100);
console.log(str1 == 100);

JavaScriptのNaNは"Not a Number"の略

数値でない結果を表す

let notNumber = "hello" * 3;
console.log(notNumber); // Outputs: NaN

let squareRoot = Math.sqrt(-1);
console.log(squareRoot); // Outputs: NaN

console.log(0 / 0);

NaNか判別する

isNaN

console.log(isNaN("hello")); // Outputs: true

JavaScriptのInfinityは無限大を表す

let infinity1 = 1 / 0;
console.log(infinity1); // Outputs: Infinity

let infinity2 = 2e308 * 2;
console.log(infinity2); // Outputs: Infinity



console.log(Infinity + 1); // Outputs: Infinity
console.log(Infinity + Infinity); // Outputs: Infinity
console.log(Infinity - Infinity); // Outputs: NaN

undifined

値が代入されていない変数や存在しないオブジェクトのプロパティ、
または何も返さない関数の戻り値はundefined

let notDefined;
console.log(notDefined); // Outputs: undefined

let obj = {};
console.log(obj.property); // Outputs: undefined

function doNothing() {}
console.log(doNothing()); // Outputs: undefined

関数に戻り値がない場合、undefinedが返される

function hello() {
    console.log("hello");
}

console.log(hello()); // hello undefined

JavaScriptのstrictモードは、より厳格なエラーチェックを提供し、一部のエラーを防ぐ

strictモードが有効  ->  数を宣言せずに使用しようとするとエラーが発生
strictモードが無効  ->  この行は新しいグローバル変数を作成

"use strict";

let v = "Hello, World!"; // OK
undeclaredVariable = "Hello, World!"; // Error: undeclaredVariable is not defined

strictモードのルール

1) 変数の宣言: strictモードでは、宣言せずに変数を使用しようとするとエラーが発生
"use strict";
x = 3.14; // This will cause an error because x is not declared

2) 読み取り専用のグローバル変数の書き換え: NaNInfinityundefinedなどの読み取り専用のグローバル変数を書き換えることはできない
"use strict";
undefined = "This will cause an error"; // Cannot assign to read only property 'undefined'

3) 重複したパラメータ名: strictモードでは、関数のパラメータ名は一意であること
"use strict";
function x(p1, p1) {}; // SyntaxError: Duplicate parameter name not allowed in this context

4) withステートメントの禁止: strictモードでは、withステートメントは禁止されている
"use strict";
with (Math){x = cos(2)}; // SyntaxError: Strict mode code may not include a with statement

5) evalの制限: strictモードでは、eval関数が新しい変数を作成したり、既存の変数を変更したりすることはできない
"use strict";
eval("var x;"); // Error: Strict mode code may not include a use of eval

ガーベージコレクション(GC)は、プログラムが動的に確保したメモリを自動的に解放するプロセス

オブジェクトがどこからも参照されなくなったとき、そのオブジェクトは"ガーベージ"(不要なもの)とみなされ、そのメモリは解放される

オブジェクトへの参照を削除することで、そのオブジェクトがガーベージコレクションの対象になることを促すことは可能

function createObject() {
    let obj = { value: 'Hello, World!' };
    return obj;
}

let myObject = createObject();
console.log(myObject.value); // Outputs: 'Hello, World!'

myObject = null; // Remove reference to the object

createObject関数は新しいオブジェクトを作成し、そのオブジェクトへの参照を返す。
その後、myObject変数にこのオブジェクトへの参照を代入。
最後に、myObject変数にnullを代入することで、オリジナルのオブジェクトへの唯一の参照を削除

JavaScriptでは、encodeURIComponent関数を使用して文字列をURLエンコードする

これは、URLの一部として安全に使用できる形式に文字列を変換する

let url = "https://example.com/?name=" + encodeURIComponent("John Doe & Friends");
console.log(url); // Outputs: https://example.com/?name=John%20Doe%20%26%20Friends

encodeURIComponent関数を使用して"John Doe & Friends"という文字列をURLエンコード。
結果は"John%20Doe%20%26%20Friends"となり、これはURLの一部として安全に使用できる。

encodeURIComponentを使用せずに文字列をそのままURLに使用すると、その文字列が特殊文字(スペース、アンパサンド(&)、等号(=)など)を含んでいる場合
予期しない結果を引き起こす可能性がある。

これらの特殊文字はURLの一部として特別な意味を持つため、そのままURLに含めるとURLの構造を壊す可能性がある。
例えば、スペースはURLでは%20にエンコードされるべきだが、そのまま使用するとURLの一部が切り離されてしまう可能性がある

組み込みオブジェクトとはグローバルオブジェクトのこと

Object: すべてのオブジェクトの基本となるオブジェクト
Function: JavaScriptの関数は実際にはFunctionオブジェクト
Boolean: 真偽値(trueまたはfalse)を表すオブジェクト
Symbol: ユニークで不変のデータ型を表すオブジェクト
Error: 実行時エラーを表すオブジェクト
Number: 数値を表すオブジェクト
Math: 数学的な定数と関数を提供するオブジェクト
Date: 日付と時間を表すオブジェクト
String: 文字列を表すオブジェクト
RegExp: 正規表現を表すオブジェクト
Array: 配列を表すオブジェクト
Map, Set, WeakMap, WeakSet: コレクションを表すオブジェクト
Promise: 非同期操作の結果を表すオブジェクト
JSON: JSONデータを解析・生成するメソッドを提供するオブジェクト
// Object
let obj = new Object();
obj.name = "John";
console.log(obj.name); // Outputs: John

// Function
let func = new Function("x", "y", "return x + y");
console.log(func(1, 2)); // Outputs: 3

// Boolean
let bool = new Boolean(false);
console.log(bool); // Outputs: false

// Symbol
let sym = Symbol("sym");
console.log(sym); // Outputs: Symbol(sym)

// Error
try {
    throw new Error("An error occurred");
} catch (e) {
    console.log(e.message); // Outputs: An error occurred
}

// Number
let num = new Number(123);
console.log(num); // Outputs: 123

// Math
console.log(Math.PI); // Outputs: 3.141592653589793

// Date
let date = new Date();
console.log(date); // Outputs: current date and time

// String
let str = new String("Hello");
console.log(str); // Outputs: Hello

// RegExp
let re = new RegExp("\\d+");
console.log(re.test("123")); // Outputs: true

// Array
let arr = new Array(1, 2, 3);
console.log(arr); // Outputs: [1, 2, 3]

// Map
let map = new Map();
map.set("key", "value");
console.log(map.get("key")); // Outputs: value

// Set
let set = new Set();
set.add(1);
console.log(set.has(1)); // Outputs: true

// Promise
let promise = new Promise((resolve, reject) => {
    resolve("Success!");
});
promise.then(console.log); // Outputs: Success!

// JSON
let json = JSON.stringify({ name: "John" });
console.log(json); // Outputs: {"name":"John"}

配列を生成する例

[値1,値2]
new Array(値1,値2)
Array.of(値1,値2)
Array.from([値1,値2])



// Method 1: Using array literal syntax
let arr1 = [1, 2, 3, 4, 5];
console.log(arr1); // Outputs: [1, 2, 3, 4, 5]

// Method 2: Using the Array constructor
let arr2 = new Array(1, 2, 3, 4, 5);
console.log(arr2); // Outputs: [1, 2, 3, 4, 5]

// Method 3: Using Array.of() method
let arr3 = Array.of(1, 2, 3, 4, 5);
console.log(arr3); // Outputs: [1, 2, 3, 4, 5]

// Method 4: Using Array.from() method
let arr4 = Array.from([1, 2, 3, 4, 5]);
console.log(arr4); // Outputs: [1, 2, 3, 4, 5]
let array = [1, 2, 3];
array[3] = 100;
console.log(array); // [ 1, 2, 3, 100 ]
console.log(array.length); // 4
console.log(array[3]); // 100
var array = [];
array[3] = 100;
console.log(array); // [ , , , 100 ]
console.log(array[0]); // undefined

let array = [1, 2, 3];
array.pop();
console.log(array); // [1, 2]

array.push(4);
console.log(array.length); // 3

array.concat([5, 6]);
console.log(array); // [1, 2, 4]
console.log(array.length); // 3

主なラッパーオブジェクト

Number
String
Boolean

プロパティ
Number:
    Number.EPSILON: JavaScriptで表現できる最小の正の数値
    Number.MAX_VALUE: JavaScriptで表現できる最大の正の数値
    Number.MIN_VALUE: JavaScriptで表現できる最小の正の数値
    Number.NaN: "Not a Number"を表す特殊な数値
    Number.NEGATIVE_INFINITY: 負の無限大を表す特殊な数値
    Number.POSITIVE_INFINITY: 正の無限大を表す特殊な数値

String:
    String.prototype.length: 文字列の長さ(文字数)を返す。
var str = "Hello,World,!!!!!";
console.log(str.length); // 15

var str2 = str.split(",");
console.log(str2); // [ 'Hello', 'World', '!!!!!' ]
console.log(str2.length); // 3

Dateオブジェクト

・年、月、日、曜日、時、分、秒を返す
・年月日、曜日、時、分、秒を設定する 
・ローカル日時を取得する

let date = new Date();

// getDate() method
console.log(date.getDate()); // Outputs: current day of the month

// getDay() method
console.log(date.getDay()); // Outputs: current day of the week (0-6)

// getFullYear() method
console.log(date.getFullYear()); // Outputs: current year

// getHours() method
console.log(date.getHours()); // Outputs: current hour (0-23)

// getMilliseconds() method
console.log(date.getMilliseconds()); // Outputs: current milliseconds (0-999)

// getMinutes() method
console.log(date.getMinutes()); // Outputs: current minutes (0-59)

// getMonth() method
console.log(date.getMonth()); // Outputs: current month (0-11)

// getSeconds() method
console.log(date.getSeconds()); // Outputs: current seconds (0-59)

// getTime() method
console.log(date.getTime()); // Outputs: milliseconds since 1 January 1970 00:00:00 UTC

// toDateString() method
console.log(date.toDateString()); // Outputs: date in the format "Wed Dec 31 1997"

// toISOString() method
console.log(date.toISOString()); // Outputs: date in the format "1997-12-31T23:00:00.000Z"

// toJSON() method
console.log(date.toJSON()); // Outputs: date in the format "1997-12-31T23:00:00.000Z"

// toLocaleDateString() method
console.log(date.toLocaleDateString()); // Outputs: date in the format "12/31/1997"

// toLocaleTimeString() method
console.log(date.toLocaleTimeString()); // Outputs: time in the format "11:00:00 PM"

// toString() method
console.log(date.toString()); // Outputs: date in the format "Wed Dec 31 1997 23:00:00 GMT+0000 (Coordinated Universal Time)"

var now = new Date();
6/5にgetMonth()を使うと5が返ってくる
6/5にgetDate()を使うと6が返ってくる
6/5にgetDay()を使うと0が返ってくる

console.log(now); // 現在の日時
console.log(now.getMonth()); // getMonth()は0から始まるので、現在の月を取得するには+1する
console.log(now.getDate()); // getDate()は1から始まる
console.log(now.getDay()); // getDay()は曜日を表す数値(0:日曜日, 1:月曜日, ..., 6:土曜日)

月と曜日は+1しないと現在の日付が出ない

var now = new Date(); // 2024-06-05T13:36:57.665Z
console.log(now.getMonth() + "月" + now.getDate() + "日" + now.getDay() + "曜日"); // 5月5日3曜日
console.log((now.getMonth()+1) + "月" + now.getDate() + "日" + (now.getDay()+1) + "曜日"); // 6月5日4曜日

RegExpオブジェクト

let regex = new RegExp('foo');

// test() method
let testResult = regex.test('foobar'); // Returns true if 'foo' is found in the string
console.log(testResult); // Outputs: true

// exec() method
let execResult = regex.exec('foobar'); // Returns an array with the match, or null if no match is found
console.log(execResult); // Outputs: ['foo', index: 0, input: 'foobar', groups: undefined]

Mathオブジェクト

// PI property
console.log(Math.PI); // Outputs: 3.141592653589793

// E property
console.log(Math.E); // Outputs: 2.718281828459045

// ceil() method
console.log(Math.ceil(3.1)); // Outputs: 4

// floor() method
console.log(Math.floor(3.9)); // Outputs: 3

// round() method
console.log(Math.round(3.5)); // Outputs: 4

var num1 = 1;
var num2 = 2;
var num3 = "3";
console.log(num1 + num2 + num3); // 33



var num1 = "100";
var num2 = "50";
console.log(num1 - num2); // 50
console.log(num1 + num2); // 10050

+演算子は文字列の連結と数値の加算の両方を行う。
-演算子は数値の減算のみを行う

num1とnum2が文字列として定義されているため、num1 + num2は文字列の連結を行う
"100"と"50"を連結して"10050"を生成する

演算の順番 ++a と a++の違い

++a 演算してから値を評価

var a = 100;
console.log(++a); //  101

a++ 値が評価されてから演算

加算前の値が表示される

var a = 100;
console.log(a++); //  100

比較演算子

var a = 100;
var b = 100;
var c = "100";
var d = "100";
console.log(a == b); // true
console.log(a === b); // true
console.log(b == c); // true
console.log(b === c); // false
console.log(c == d); // true
console.log(c === d); // true


// == で比較すると数値と文字列、真偽値も数値に変換して比較される
// === だと変換はされない。なのでfalseになる
console.log(a == c); // true
console.log(a === c); // false

delete 演算子

配列の要素やオブジェクトのプロパティを削除する
削除されたらundefinedになる

var emp = { name: "John", age: 30 };
var empName = emp.name;

delete emp.name;
delete empName;

console.log(emp.name); // undefined
console.log(empName); // "John"



var arr = [1, 2, 3, 4, 5];
delete arr[0];
console.log(arr); // [ <1 empty item>, 2, 3, 4, 5 ]
console.log(arr[0]); // undefined
console.log(arr.length); // 5

instanceof演算子

オブジェクトが特定のクラスのインスタンスであるかどうかを判定する

var val1 = "hello";
var val2 = new String("hello");

console.log(val1 instanceof Object); // false
console.log(val2 instanceof Object); // true


console.log(val1 instanceof String); // false
console.log(val2 instanceof Object); // true

in演算子

var cat = { name: "Fluffy", age: 3 };
console.log("name" in cat); // true
console.log("bark" in cat); // false

cat.bark = function() { console.log("Meow!"); }
console.log("toString" in cat); // true


console.log(cat); // { name: 'Fluffy', age: 3, bark: [Function: bark] }

typeof演算子

var str1 "hello";
var str2 = new String("hello");
var arr = ["banana", "apple", "orange"];

console.log(typeof str1); // string
console.log(typeof str2); // object
console.log(typeof arr); // object

void演算子

式を評価してundefinedを返す

switch 失敗例

各caseの最後にbreak文を追加しないと失敗する

let fruit = "apple";

switch (fruit) {
  case "apple":
    console.log("Apple is $1");
    // break; // Forgot to break here
  case "banana":
    console.log("Banana is $2");
    break;
  default:
    console.log("Unknown fruit");
    break;
}
// 11ずつ増加していく
// 55を超えたら6を足していく
// 100になるまで繰り返す
var num = 0;
while (num < 100) {
  if (num > 55) {
    num += 6;
  }
  num += 11;
}
console.log(num); // 100


// 66 + 17 = 83
// 83 + 17 = 100
var num = 100;
do {
    if (num > 55) {
        num += 6;
    }
    num += 11;
} while (num < 100);

console.log(num); // 117

for/inは処理の順番が保証されない

このコードは、objのプロパティをループする
出力される順序は"b: 2", "a: 1", "c: 3"とは限らない

let obj = {
    "b": 2,
    "a": 1,
    "c": 3
  };
  
for (let prop in obj) {
    console.log(`${prop}: ${obj[prop]}`);
}
// for/ofは順番を保証する
let arr = [3, 1, 4];

for (let value of arr) {
  console.log(value);
}

for break/coninue

let arr = [1, 2, 3, 4, 5];

// Using break
// 処理を終了する
for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 3) {
    break; // Stops the loop when the element is 3
  }
  console.log(arr[i]); // Outputs: 1, 2
}

// Using continue
// 処理をスキップする
for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 3) {
    continue; // Skips the current iteration when the element is 3
  }
  console.log(arr[i]); // Outputs: 1, 2, 4, 5
}

try-catch-finally

try {
    // Try to execute this code
    let value = 5;
    if(value < 10) {
      throw new Error('Value is less than 10');
    }
} catch (error) {
    // If an error occurs in the try block, catch it
    console.log('An error occurred: ' + error.message);
} finally {
    // This code is executed regardless of whether an error occurred or not
    console.log('The try-catch block has finished executing');
}

// Outputs: An error occurred: Value is less than 10    
//          The try-catch block has finished executing

try {
    // Try to execute this code
    throw new Error('Something went wrong');
} catch (error) {
    // If an error occurs in the try block, catch it
    console.log('Error name: ' + error.name); // Outputs: "Error name: Error"
    console.log('Error message: ' + error.message); // Outputs: "Error message: Something went wrong"
    console.log('Error stack: ' + error.stack); // Outputs the stack trace at the point where the Error was instantiated
}

// Set the stackTraceLimit
Error.stackTraceLimit = 10;

関数宣言の例

関数名を付けて宣言する
関数名を省略して記載する

function namedFunction() {
    console.log('This is a named function');
}
namedFunction(); // Call the named function
  

// 無名関数として宣言する 
// 関数を変数に代入して使う
let anonymousFunction = function() {
    console.log('This is an anonymous function');
};
anonymousFunction(); // Call the anonymous function
  

// 即時実行関数として宣言する
// 関数定義後、スクリプトが読み込まれるとすぐに呼び出されて実行される
(function() {
    console.log('This is an immediately invoked function expression');
})(); // Declare and call the IIFE

ローカルスコープ

var val = 100;
function increment(val) {
  return ++val;
}

console.log(increment(val)); // 101
console.log(val); // 100

オブジェクト型は参照先がコピーされる

よってコピー元の配列の値も変わる

var scores = [80, 90, 85, 95];

function sortScores(val) {
    return val.sort();
}

console.log(sortScores(scores)); // [ 80, 85, 90, 95 ]
console.log(scores); // [ 80, 85, 90, 95 ]

オブジェクトの生成方法

// 1)
var cat = {name: "Tom"};

// 2)
var cat = {"name": "Tom"};

// 3)
var cat = {}; 
cat.name = "Tom";


// 上記のnameプロパティの値のアクセス
console.log(cat.nam); // Tom 
console.log(cat["name"]); // Tom





var cat = {name: "Tom", type: "Tabby"};
cat.age = 1.4;
cat[222] = "猫の日";
cat["111111"] = "猫の日";
cat.type = null;
cat // { name: 'Tom', type: null, age: 1.4, '222': '猫の日', '111111': '猫の日' }

オブジェクトのコンストラクタの手順

// 1) コンストラクタ関数を定義
function Car(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
}
// 2) new演算子でインスタンスを生成
let myCar = new Car('Toyota', 'Corolla', 2005);

console.log(myCar); // Outputs: Car { make: 'Toyota', model: 'Corolla', year: 2005 }

JavaScriptのプロトタイプチェーン

オブジェクトが他のオブジェクトからプロパティとメソッドを継承する仕組み

// Define a constructor function
function Vehicle(type) {
    this.type = type;
}
  
// Add a method to the Vehicle prototype
Vehicle.prototype.start = function() {
    return `Starting the ${this.type}`;
}


  
// Define a constructor function for Car that inherits from Vehicle
function Car(make, model) {
    Vehicle.call(this, 'car'); // Call the parent constructor function
    this.make = make;
    this.model = model;
}

// Set up the prototype chain
Car.prototype = Object.create(Vehicle.prototype); // Car now inherits from Vehicle
Car.prototype.constructor = Car; // Set the constructor property to Car

// Add a method to the Car prototype
Car.prototype.display = function() {
    return `${this.make} ${this.model}`;
}

// Create a new car object
let myCar = new Car('Toyota', 'Corolla');

console.log(myCar.start()); // Outputs: "Starting the car"
console.log(myCar.display()); // Outputs: "Toyota Corolla"

JavaScriptの全てのオブジェクトはObject.prototypeを継承している

prototypeプロパティはオブジェクトのプロトタイプを拡張する

function Cat() {}
Cat.prototype.play = function() {
    return "The cat is playing";
}
function Animal(name) {
    this.name = name;
}

Animal.prototype.type = "cat";

var animals = [new Animal("ラム"), new Animal("ハム"), new Animal("トム")];
animals[1].type = "dog";

console.log(animals); 
// [
//     Animal { name: 'ラム' },
//     Animal { name: 'ハム', type: 'dog' },
//     Animal { name: 'トム' }
// ]


for (let animal of animals) {
    console.log(animal.name + " is a " + animal.type);
}
// ラム is a cat
// ハム is a dog
// トム is a cat

thisキーワード

  1. グローバル実行コンテキスト

  2. 非strictモードの呼び出し

  3. strictモードの呼び出し

  4. オブジェクトのメソッド

  5. コンストラクタ内

  6. コールバック関数

// 1) Global execution context
console.log(this); // Outputs: Window {...} (or {} in Node.js)

// 2) Non-strict mode function call
function nonStrictFunction() {
  console.log(this);
}
nonStrictFunction(); // Outputs: Window {...} (or global in Node.js)

// 3) Strict mode function call
"use strict";
function strictFunction() {
  console.log(this);
}
strictFunction(); // Outputs: undefined

// 4) Object method
let obj = {
  name: 'Object',
  display: function() {
    console.log(this);
  }
};
obj.display(); // Outputs: { name: 'Object', display: [Function: display] }

// 5) Constructor
function Car(make, model) {
  this.make = make;
  this.model = model;
}
let myCar = new Car('Toyota', 'Corolla');
console.log(myCar); // Outputs: Car { make: 'Toyota', model: 'Corolla' }

// 6) Callback function
let anotherObj = {
  name: 'Another Object',
  display: function(callback) {
    callback();
  }
};
anotherObj.display(function() {
  console.log(this);
}); // Outputs: Window {...} (or global in Node.js)

this === window

var cat = {
    greet: function() {
        console.log(this === window); // false
    }
}

function myao() {
    console.log(this === window); // true
}

function woo() {
    "use strict";
    console.log(this === window); // false
}


cat.greet();
myao();
woo();
console.log(this === window); // true

グローバル変数とローカル変数

var global = "Global variable";

function func() {
  var local = "Local";
  console.log(global); // Accessible
}

func();
console.log(local); // エラー発生: Uncaught ReferenceError: local is not defined

var val = "A";

function print() {
  console.log(val); 
  var val = "B";
  return val;
}

console.log(print()); 
console.log(val); 

スコープチェーンは、変数や関数の参照を解決するためのメカニズム

// Global scope
var globalVar = 'Global Variable';

function outerFunction() {
  // Outer function scope
  var outerVar = 'Outer Variable';

  function innerFunction() {
    // Inner function scope
    var innerVar = 'Inner Variable';

    console.log(innerVar); // Outputs: "Inner Variable"
    console.log(outerVar); // Outputs: "Outer Variable"
    console.log(globalVar); // Outputs: "Global Variable"
  }

  innerFunction();
}

outerFunction();
func1();

function func1() {
    console.log("Hello, World!");
}



// これは関数リテラル代入後に、呼び出さないとTypeErrorになる

func2();
var func2 = function() {
    console.log("Hello, World!");
}

クロージャ

catName関数はclosure関数を返す 

closure関数は、それが定義されたスコープ(catName関数のスコープ)のname変数を参照する

catName関数の実行が終了した後でも、closure関数はname変数にアクセスできる

closure関数がname変数を「クローズ」(つまり、保持)しているため

function catName() {
  var name = "Fluffy";
  function closure() {
    return name;
  }
  return closure;
}

var test = catName();
console.log(test()); // Outputs: "Fluffy"

このコードでは、return closure;はclosure関数を呼び出すのではなく、closure関数自体を返す。
関数名の後に括弧 () がない場合、それは関数の呼び出しではなく、関数オブジェクトそのものを指すため。

したがって、return closure;はclosure関数オブジェクトを返す。
その結果、catName()の呼び出しはclosure関数を返し、それがtest変数に代入される

そのため、test()とすると、実際にはclosure関数が呼び出される。
このclosure関数は、それが定義されたスコープ(catName関数のスコープ)のname変数を参照し、その値("Fluffy")を返す(クロージャ)

グローバルオブジェクト

ブラウザにおけるグローバルオブジェクトはwindowオブジェクト

グローバルオブジェクトは全てのスコープから参照できる

With

・一時的にスコープチェーンを拡張する
・指定したオブジェクトのプロパティを直接参照できる新しいスコープを作成する
・使用された識別子をスコープチェーン上で検索する
・識別子の検索は、指定されたオブジェクト、スコープチェーンの順で実行する
・strictモードでは使用できない

var obj = {
  prop1: 'Property 1',
  prop2: 'Property 2'
};

// withステートメントはobjオブジェクトのプロパティを直接参照できる新しいスコープを作成
// その結果、わざわざobj.prop1とobj.prop2と書かなくても、prop1とprop2と書ける
with (obj) {
  console.log(prop1); // Outputs: "Property 1"
  console.log(prop2); // Outputs: "Property 2"
}




var cat = { name: "Fluffy", age: 3 };
cat.type = "Tabby";
with(cat) {
  console.log(name); // Fluffy
  console.log(age); // 3
}

withを使わない例

document.querySelector("#myElement").style.color = "red";
document.querySelector("#myElement").style.fontSize = "16px";
document.querySelector("#myElement").style.fontWeight = "bold";

withを使ってオブジェクト名を省略した例

with(document.querySelector("#myElement").style) {
  color = "red";
  fontSize = "16px";
  fontWeight = "bold";
}

withを使わずにオブジェクト名を省略した例

var style = document.querySelector("#myElement").style;
style.color = "red";
style.fontSize = "16px";
style.fontWeight = "bold";

オブジェクトの継承、Function.call()

function Car(speed, fuel) {
  this.speed = speed;
  this.fuel = fuel;
}

function Track(speed, fuel, loadage) {
  Car.call(this, speed, fuel); // thisを指定して、Carコンストラクタ内のthisをTruckオブジェクトに置き換える
  this.loadage = loadage;
}

var myTrack = new Track(100, 50, 500);
console.log(myTrack); // Outputs: Track { speed: 100, fuel: 50, loadage: 500 }


var message = "Hello";
var funcA = function () {
  function funcB() {
    console.log(message + "funcB");
  }
  console.log(message + "funcA");
};

function funcC(f) {
  var message = new String("byte");
  f();
  funcA();
  funcB(); // funcC内ではfuncBは呼び出せない エラーになる
}

funcC(funcA);



funcC内ではfuncBは呼び出せない エラーになる
funcB();を消せば、
  HellofuncA
  HellofuncA
と表示される
(funcB()の参照が書いてないため)

parseInt()関数

console.log(parseInt('15')); // Outputs: 15

console.log(parseInt('15.99')); // Outputs: 15
  -> 小数点以下を切り捨てる

console.log(parseInt('15abc')); // Outputs: 15
  -> 数値以外は無視される

console.log(parseInt('   15')); // Outputs: 15
  -> 先頭の空白を無視する

console.log(parseInt('F', 16)); // Outputs: 15
console.log(parseInt('0xf')); // Outputs: 15
  -> 16進数として解釈される




// 解析できない文字列は NaN を返す
console.log(parseInt('')); // Outputs: NaN
console.log(parseInt('aaaaaaaaaa')); // Outputs: NaN

この記事が気に入ったらサポートをしてみませんか?