
JavaScriptのイベント処理:クリック、フォーム入力からバブリング・デリゲーションまで
はじめに JavaScriptのイベント処理は、インタラクティブなウェブアプリケーション開発の核心です。ユーザーのクリック、フォーム入力、キーボード操作など、あ […]
アロー関数(Arrow Function)はES6(ECMAScript 2015)で導入された、より簡潔な関数記法です。=>
の見た目から「矢印関数」とも呼ばれます。
// 従来の関数式
const add = function(a, b) {
return a + b;
};
// アロー関数
const add = (a, b) => {
return a + b;
};
単一式の場合:return
と{}
を省略可能
// 従来
const square = function(x) {
return x * x;
};
// アロー関数
const square = x => x * x;
引数が1つの場合:()
を省略可能
const double = x => x * 2;
this
の扱いアロー関数は独自のthis
を持たず、外側のスコープのthis
を継承します(レキシカルスコープ)。
const person = {
name: '太郎',
traditionalFunc: function() {
console.log(this.name); // '太郎'
},
arrowFunc: () => {
console.log(this.name); // undefined(外側のthisを参照)
}
};
const Person = (name) => {
this.name = name; // TypeError
};
// new Person('太郎'); // エラー
arguments
オブジェクトが無いconst traditional = function() {
console.log(arguments);
};
const arrow = () => {
// console.log(arguments); // エラー
console.log(...arguments); // 残余パラメータを使用
};
traditional(1, 2, 3); // Arguments(3) [1, 2, 3]
// arrow(1, 2, 3); // エラー
const func = (arg1, arg2) => {
// 処理
return result;
};
const greet = () => {
console.log('Hello!');
};
const square = x => {
return x * x;
};
const square = x => x * x;
const createUser = (name, age) => ({
name: name,
age: age
});
// プロパティ名の短縮記法
const createUser = (name, age) => ({ name, age });
const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2);
this
のバインドが必要ない場合 const button = document.querySelector('button');
button.addEventListener('click', () => {
console.log('Clicked!');
});
const isEven = num => num % 2 === 0;
// 👎 非推奨
const obj = {
value: 10,
getValue: () => this.value // undefined
};
// 👍 推奨
const obj = {
value: 10,
getValue() { return this.value; }
};
// 👎 できない
const Person = name => {
this.name = name;
};
// 👍 関数宣言を使用
function Person(name) {
this.name = name;
}
this
が必要な場合 // 👎 thisが期待通りにならない
button.addEventListener('click', () => {
console.log(this); // 期待するthisではない
});
// 👍 通常の関数を使用
button.addEventListener('click', function() {
console.log(this); // button要素
});
特徴 | アロー関数 | 通常関数 |
---|---|---|
this の扱い | レキシカルスコープ | 呼び出し元に依存 |
arguments オブジェクト | ❌ 無し | ✅ 有り |
コンストラクタとして使用 | ❌ 不可 | ✅ 可能 |
簡潔な構文 | ✅ 可能 | ❌ 不可 |
メソッド定義 | ⚠️ 不適 | ✅ 適切 |
ホイスティング | ❌ 無し | ✅ 有り(関数宣言) |
const numbers = [1, 2, 3, 4, 5];
// 偶数のみフィルタリング
const evens = numbers.filter(n => n % 2 === 0);
// 各要素を2乗
const squares = numbers.map(n => n * n);
// 合計を計算
const sum = numbers.reduce((acc, n) => acc + n, 0);
// Promiseチェーン
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => console.error(error));
const createMultiplier = factor => x => x * factor;
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
// 👎 動かない({}がブロックと解釈される)
const createUser = (name, age) => { name, age };
// 👍 正しい書き方
const createUser = (name, age) => ({ name, age });
// 複数行の場合は明示的なreturnが必要
const process = (x, y) => {
const sum = x + y;
const product = x * y;
return { sum, product };
};
// 匿名関数としてスタックトレースに表示される
const func = () => {
throw new Error('エラー発生');
};
func(); // スタックトレースで"func"ではなく"anonymous"と表示
function multiply(a, b) {
return a * b;
}
const greet = name => `こんにちは、${name}さん!`;
console.log(greet('太郎'));
const numbers = [1, 2, 3];
const squared = numbers.map(function(x) {
return x * x;
});
const getFullName = (firstName, lastName) => `${firstName} ${lastName}`;
const counter = {
count: 0,
increment: function() {
this.count++;
}
};
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const isPositive = number => {
return number > 0;
};
const obj = {
value: 10,
traditional: function() {
console.log(this.value);
},
arrow: () => {
console.log(this.value);
}
};
obj.traditional();
obj.arrow();
const createTransformer = transform => str => transform(str);
add
をアロー関数で実装しなさい。console.log(add(2)(3)(4)()); // 9
pipe
関数をアロー関数で実装しなさい。const double = x => x * 2;
const square = x => x * x;
const piped = pipe(double, square);
console.log(piped(5)); // 100 (5*2 = 10, 10^2 = 100)
createCounter
関数を実装しなさい。javascript const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
const multiply = (a, b) => a * b;
こんにちは、太郎さん!
const greet = name => `こんにちは、${name}さん!`;
console.log(greet('太郎')); // こんにちは、太郎さん!
const squared = numbers.map(x => x * x);
function getFullName(firstName, lastName) {
return `${firstName} ${lastName}`;
}
// アロー関数にするとthisが期待通りにならない
const counter = {
count: 0,
increment: () => {
this.count++; // thisはcounterオブジェクトを指さない
}
};
const result = numbers
.filter(n => n % 2 === 0)
.map(n => n * 2);
const isPositive = number => number > 0;
10
undefined
const obj = {
value: 10,
traditional: function() {
console.log(this.value); // obj.valueの値を参照
},
arrow: () => {
console.log(this.value); // thisは外側のスコープを参照するため、undefinedになる
}
};
obj.traditional();
obj.arrow();
const reverseString = createTransformer(str =>
str.split('').reverse().join('')
);
console.log(reverseString('hello')); // 'olleh'
const add = a => b => c => () => a + b + c;
pipe
関数const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
createCounter
関数javascript const createCounter = () => {
let count = 0;
return () => ++count;
};