Review-ES 6構文(3)


今はES 6文法の最後の編です.
これに対して全面的な復習を行う.

これは何ですか。


自分が属するオブジェクトまたは自分が作成するインスタンスの自己参照変数を指します.
関数の呼び出し方法に応じて、バインド(識別子を値に関連付けるプロセス)が動的に決定されます.

関数呼び出し方式


関数呼び出しの方式に応じて動的に決定します.
ex)
let foo = function () {
  console.dir(this);
};
上記のコードを例に挙げます.

1.一般関数の呼び出し


foo関数は通常の方法で呼び出され、foo関数の内部はグローバルオブジェクトwindowを指す.
ex)
foo(); // window

2.呼び出し方法


foo関数を属性値として指定して呼び出すことで、foo関数内部のこれは呼び出し方法のオブジェクトobjを指す.
ex)
let obj = { foo };
obj.foo(); // obj

3.コンストラクタの呼び出し


foo関数はnew演算子とともにコンストラクション関数として呼び出され、foo関数内部のこれはコンストラクション関数生成の例を指す.
ex)
new foo(); // foo {}

4. Function.prototype.apply/call/bindメソッドによる間接呼び出し


foo関数内部のこの点は因数によって決まる.
ex)
let bar = { name: 'bar' };

foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar

このバインディング


これは、関数呼び出しの方法に依存します.

1.一般関数の呼び出し


通常の関数として呼び出されるすべての関数内部のthisは、グローバルオブジェクトをバインドします.
ex)
function foo() {
  console.log("foo's this: ", this); // window
  function bar() {
    console.log("bar's this: ", this); // window
  }
  bar();
}
foo();

2.呼び出し方法


メソッド内のthisは、メソッドを呼び出すときにメソッド名の前の句点(.)演算子で先に説明したオブジェクトをバインドします.
ex)
function Person(name) {
  this.name = name;
}

Person.prototype.getName = function() {
  return this.name;
};

let me = new Person('Yeon');

// getName 메서드를 호출한 객체는 me이다.
console.log(me.getName()); // Yeon

Person.prototype.name = 'Shin';

// getName 메서드를 호출한 객체는 Person.prototype이다.
console.log(Person.Prototype.getName()); // Shin

3.コンストラクタの呼び出し


コンストラクション関数の内部にあるthisでは、コンストラクション関数は将来作成するインスタンスをバインドします.
ex)
function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function() {
    return 2 * this.radius;
  };
};

// 반지름이 10인 Circle 객체를 생성한다.
let circle1 = new Circle(10);
// 반지름이 20인 Circle 객체를 생성한다.
let circle2 = new Circle(20);

console.log(circle1.getDiameter()); // 20
console.log(circle2.getDiameter()); // 40

4. Function.prototype.apply/call/bindメソッドによる間接呼び出し


1. Function.prototype.apply, Function.prototype.コールメソッド


この目的で使用するオブジェクトとパラメータのリストをパラメータとして渡し、関数として呼び出します.

指定したthisバインドとパラメータリスト配列を使用して関数を呼び出します.
Function.prototype.apply(thisArg[, argsArray])
thisArg:この目的のオブジェクトとして使用
ArgsArray:関数に渡すパラメータリストの配列または類似配列オブジェクト
呼び出し関数の戻り値を返します.

指定されたthisバインドと,で区切られたパラメータリストを使用して関数を呼び出します.
Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
thisArg:この目的のオブジェクトとして使用
arg1, arg2, ... : 関数に渡すパラメータのリスト
呼び出し関数の戻り値を返します.
ex)
function getThisBinding() {
  console.log(arguments);
  return this;
}

// this로 사용할 객체
let thisArg = { a: 1 };

// getThisBinding 함수를 호출하면서 인수로 전달할 객체를 getThisBinding 함수의 this에 바인딩한다.
// apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달한다.
console.log(getThisBinding.apply(thisArg, [1, 2, 3])); 
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// {a: 1}

// call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달한다.
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// {a: 1}

2. Function.prototype.bindメソッド


関数は呼び出されず、この関数として使用されるオブジェクトのみが渡されます.
ex)
function getThisBinding() {
  return this;
}

// this로 사용할 객체
let thisArg = { a: 1 };

// bind 메서드는 함수에 this로 사용할 객체를 전달한다.
// bind 메서드는 함수를 호출하지는 않는다.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
console.log(getThisBinding.bind(thisArg)()); // {a: 1}

整理する


関数呼び出し方式
このバインディング
一般関数の呼び出し
グローバルオブジェクト
メソッド呼び出し
メソッドを呼び出すオブジェクト
コンストラクタの呼び出し
コンストラクション関数が将来作成するインスタンス
Function.prototype.apply/call/bindメソッドによる間接呼び出し
Function.prototype.apply/call/bindメソッドに最初の引数として渡されるオブジェクト