はじめに
初学者です。
基本は備忘録
関数とthis
function fn(a, b) {
console.log(a, b);
}
fn(1) //結果: 1 undefined
fn(null, 1)//結果 null 1
//2つめだけ使いたい場nullを使う
jsでは同じ関数が2つ以上ある場合後に書いた方が実行される
関数式で宣言するとエラーで教えてくれる
function fn(a, b = 2) { //デフォルト値を設定できる
console.log(a, b);
}
fn(1, null)// 1 null
fn(1, undefined)// 1 2
//意図的に空にしたい場合はnullにする。undefinedは基本使わない
argumentsとは
function fn(a, b) {
console.log(a, b);
}
fn(1, 2)
argumentsとは実引数のことである
上記のコードだと1と2が該当する
関数とオブジェクト
関数は実行可能なオブジェクトである
実行可能な点以外は全て一緒
コールバック関数
他の関数の引数として渡された関数のこと
function hello(name) {
console.log('hello' + name)
}
function fn(cd) {
cb('Ren')
}
fn(hello)//結果: hello Ren
//実引数(上記だとhello)がコールバック関数
コールバック関数は無名関数を使って直接記述しても使用可能
function greet() {
console.log('Hello')
}
setTimeout(greet, 2000)//2秒後にHelloと表示
//greetがコールバック関数
なぜコールバック関数が存在するのか?
上記のコードは「○秒後に実行」+「helloと表示」の2つの関数で成り立っている
関数helloを別なものに変更するだけで変更した関数も○秒後に発動できる
処理を切り分けることでコードの再利用性が高まっている
thisについて
thisは呼び出し元のオブジェクトへの参照を保持する
実行コンテキストによってthisの参照先は変わる
const person = {
name: 'Ren',
hello: function() {
console.log('Hello' + this.name)
}
}
person.hello() //結果 Hello Ren
//thisは呼び出し元のpersonを参照している
参照のコピーとthis
window.name = 'Miku'
const person = {
name: 'Ren',
hello: function() {
console.log('Hello' + this.name)
}
}
const ref = person.hello
ref(); //Hello Miku
//refにはhello()の参照先の関数が渡されるのでオブジェクトを経由しない。
//thisはレキシカルスコープのwindowを参照する
以下のように考えることができる
オブジェクトのメソットとして実行される場合
'this' => 呼び出し元のオブジェクト
関数として実行される場合
'this' => グローバルオブジェクト
コールバック関数とthis
window.name = 'Miku'
const preson = {
name: 'Ren',
hello: function() {
console.log('Hello', this.name)
}
}
function fn(ref) {
ref();
}
fn(person.hello)//Hello Miku
//refにはメソットの参照先の関数が直接入る(関数への直接の参照)
//オブジェクトは経由しないため、thisにはwindowオブジェクトが格納される
//レキシカルスコープはfnだが関数として実行されているためwindowオブジェクトを参照
メソットを他の変数に代入すると、オブジェクト経由で呼び出すのではなく関数を格納している変数から直接呼ぶため、呼び出し元のオブジェクトは基本的にwindowオブジェクトになる
bindとthis
bindを使うことでthisや引数を固定することができる
bindによるthisの束縛と呼ぶ
bindで固定する場合元の関数とは別の関数が新しく作成される
const preson = {
name: 'Ren',
hello: function() {
console.log('Hello', this.name)
}
}
const helloRen = person.hello.bind(person);
//person.helloのthisの参照を固定できる
function fn(ref) {
ref();
}
fn(helloRen)//結果 Hello Ren;
---------------------------------------------------------
function a() {
console.log('hello' + this.name);
}
const b = a.bind({name: 'Ren'});
b()//結果 hello Ren
引数を固定
function a(name) {
console.log('Hello' + name);
}
const b = a.bind(null, 'Ren')
//第一引数はthis,第二引数は引数を固定する
//thisを必要としない場合nullにする
b()//結果: Hello Ren
applyとcall
bindとの違いは定義と同時に実行までされる点
function a(name, name1) {
console.log('Hello ' + name + ' ' + name1);
}
const tim = {name: 'Tim'};
a.apply(tim, ['Ren', 'Miku']);//第一引数はthis,第二引数は(配列)を固定する
a.call(tim, 'Ren', 'Miku');//第一引数はthis,第二引数は引数を固定する
//applyとcallは定義するのと同時に実行まで行われる
アロー関数とは
無名関数を記述しやすくした省略記法
const b = (name) => {
return 'hello' + name;
}
//引数が1つなら()は省略できる
//実行行が1行なら{}とreturnは省略できる
const b = name => 'hello' + name;
console.log(b('Ren'))//結果: hello Ren
無名関数とアロー関数の挙動には違いがある
- | 無名関数 | アロー関数 |
---|---|---|
this | ○ | x |
arguments | ○ | x |
new | ○ | x |
prototype | ○ | x |
アロー関数とthis
アロー関数はthisを保持しないためレキシカルスコープに探しに行く
アロー関数はthiwを保持しないのでbind等で束縛もできない
const person = {
name: 'Ren';
hello: function() {
console.log('Hello' + this.name)//Hello Ren
//無名関数はthisを保持するためオブジェクトへの参照を保持
}
}
window.name = 'Miku';
const person = {
name: 'Ren';
hello: () => {
console.log('Hello' + this.name)// Hello Miku
//アロー関数はthisを保持しないためレキシカルスコープ参照
//このコードだとwindowオブジェクトがレキシカルスコープ
}
}
window.name = 'Miku';
const person = {
name: 'Ren';
hello() {
console.log('Hello' + this.name)// Hello Ren
const a = () => console.log('Bye' + this.name)
a();// Hello Ren
}
}
//アロー関数はthisを保持しないためレキシカルスコープを参照
//このコードだと関数helloの関数スコープがレキシカルスコープ
//関数helloはメソットとして実行しているのでthisを保持している