var a = 1;
console.log(a); // 1
console.log(window.a); // 1
console.log(this.a); // 1
var a = 1;
window.b = 2;
console.log(a, window.a, this.a); // 1 1 1
console.log(b, window.b, this.b); // 2 2 2
전역변수 선언과 전역객체의 프로터티 할당 시 같은 결과가 나온다.
하지만, 전역변수 선언과 전역객체의 프로터티 할당 사이에서 차이가 나는 경우가 있다. 바로 호이트싱 여부 및 configurable(변경 및 삭제 가능성) 여부이다.
아래는 전역 변수, 전역 객체의 삭제 동작이다:
var a = 1;
delete window.a; // false
console.log(a, window.a, this.a); /// 1 1 1
window.c = 3;
delete window.c; // true
console.log(c, window.c, this.c); // Uncaught ReferenceError: c is not defined
위 예시에서 차이점이 나온다. 변수에 delete연산자를 사용할 때 (window.)를 생략한 것으로 이해하면 된다.
var func = function(x) {
console.log(this, x);
};
func(1); // Window {...} 1
var obj = {
method: func
}
obj.method(2); // { method: f } 2
어떤 함수를 메서드로서 호출하는 경우, 호출 주체는 바로 함수명(프로퍼티명) 앞의 객체이다.
var obj = {
methodA: function () { console.log(this); },
inner: {
methodB: function () { console.log(this); }
}
};
object.methodA(); // {methodA: f, inner: {...} } ( === obj )
object.inner.methodB(); // {methodB: F} ( === obj.inner)
1) 함수 내부에서의 this
2) 메서드 내부함수에서의 this
var obj1 = {
outer: function() {
console.log(this); // (1) obj1
var innerFunc = function() {
console.log(this); // (2) 전역객체(window) (3)obj2
}
innerFunc(); // --- (2) 실행
var obj2 = {
innerMethod : innerFunc
};
object2.innerMethod(); // --- (3) 실행
}
}
obj1.outer(); // ----(1) 실행
var obj = {
outer: function() {
console.log(this); // (1) { outer: f}
var innerFunc = () => {
console.log(this);
};
innerFunc();
}
}
obj.outer();
콜백함수 호출 시 그 함수 내부에서의 this
생성자 함수 내부에서의 this
예시)
var Cat = function(name, age) { // Cat 변수에 익명 함수 할당
this.bark = "야옹";
this.name = name;
this.age = age;
}
var choco = new Cat('초코', 7); // 생성자 함수 내부에서의 this는 choco 인스턴스
console.log(choco);
// Cat { bark: "야옹", name: "초코", age: 7} --- Cat 클래스의 인스턴스 객체 출력
Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
var func = function (a, b, c) {
console.log(this, a, b, c);
}
func(1, 2, 3); // Window{ ... } 1 2 3
func.call({ x: 1}, 4, 5, 6); // { x:1 } 4 5 6
Function.prototype.apply(thisArg[, argsArray])
var func = function (a, b, c) {
console.log(this, a, b, c);
}
func(1, 2, 3); // Window{ ... } 1 2 3
func.apply({ x: 1}, [4, 5, 6]); // { x:1 } 4 5 6
call / apply 메서드를 활용해 중복을 줄일 수 있다. 아래 예시는 생성자 내부에 다른 생성자와 공통된 내용이 있을 경우 call 또는 apply를 이용해 다른 생성자를 호출해 반복을 줄이는 예시이다:
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
function Student(name, gender, school) {
Person.call(this, name, gender);
this.school = school;
}
function Employee(name, gender, company) {
Person.call(this, name, gender);
this.company = company;
}
var by = new Student("보영", "female", "단국대");
var jn = new Employee("재난", "male", "구글");
함수 바인딩이란 특정한 this값과 특정한 매개변수를 넘기면서 다른 함수를 호출하는 함수입니다. 많은 자바스크립트 라이브러리들은 함수를 특정한 컨텍스트에 묶는 함수를 만들었습니다. 일반적으로 이런 함수를 bind()라고 부릅니다. 기본 구조는 아래와 같습니다. (출처: https://blog.sonim1.com/158)
function bind(fn, context){
return function(){
return fn.apply(context, arguments);
}
}
ECMAScript5에서 bind()메서드가 도입되었으며 아래와 같이 사용합니다.
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
var func = function (a, b, c, d){
console.log(this, a, b, c, d);
}
func(1, 2, 3, 4); // Window{...} 1 2 3 4
var bindFunc1 = func.bind({ x: 1 });
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
var bindFunc2 = func.bind({ x: 1 }, 4, 5);
bindFunc2(6, 7); // { x: 1} 4 5 6 7
bindFunc2(8, 9); // { x: 1} 4 5 8 9
var obj = {
outer: function() {
console.log(this); // { outer: [Function: outer] }
var innerFunc = () => {
console.log(this); // { outer: [Function: outer] }
}
innerFunc();
}
}
obj.outer();
5) 별도의 인자로 this를 받는 경우 (콜백 함수 내에서의 this)
foreach 메서드 예시:
var report = {
sum: 0,
count: 0,
add: function () {
// arguments 를 배열로 변환해서 args 변수에 담는다
var args = Array.prototype.slice.call(arguments);
// 해당 배열(args)를 순회하면서 콜백 함수 실행
args.forEach(function (entry) {
this.sum += entry;
++this.count;
}, this); // 콜백 함수 내부에서의 this가 해당 this로 바인딩 됨!
},
average: function () {
return this.sum / this.count;
},
};
report.add(60, 85, 95);
console.log(report.sum, report.count, report.average()); // 240 3 80
- 정재남, 『코어 자바스크립트』, 위키북스(2019), p65-93.
- 19. 자바스크립트 - 함수 바인딩