함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효
하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.
단, let keyword
를 사용하여 변수를 생성하면 블록 레벨 스코프를 사용할 수 있다.
var x = 0;
{
var x = 1;
console.log(x); // 1
}
console.log(x); // 1
let y = 0;
{
let y = 1;
console.log(y); // 1
}
console.log(y); // 0
변수 | 재선언 여부 | 재할당 여부 | 변수의 범위 |
---|---|---|---|
var | O | O | function {}, 함수 내에서 선언시 함수 내에서만 사용 |
let | X | O | {} |
const | X | X | {} |
렉시컬 스코프는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정
된다. 자바스크립트는 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다. 함수를 어디에서 호출하였는지는 스코프 결정에 아무런 의미를 주지 않는다.
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
apply() 메소드를 호출하는 주체는 함수이며 apply() 메소드는 this를 특정 객체에 바인딩할 뿐 본질적인 기능은 함수 호출이다.
func.apply(thisArg, [argsArray])
// thisArg: 함수 내부의 this에 바인딩할 객체
// argsArray: 함수에 전달할 argument의 배열
arguments 객체와 같은 유사 배열 객체에 배열 메소드를 사용할 때
아래와 같이 사용된다.
function convertArgsToArray() {
console.log(arguments);
// arguments 객체를 배열로 변환
// slice: 배열의 특정 부분에 대한 복사본을 생성한다.
var arr = Array.prototype.slice.apply(arguments); // arguments.slice
// var arr = [].slice.apply(arguments);
console.log(arr);
return arr;
}
convertArgsToArray(1, 2, 3); // [1,2,3]
apply()와 기능은 같지만 apply()의 두번째 인자에서 배열 형태로 넘긴 것을 각각 하나의 인자
로 넘긴다.
Person.apply(foo, [1, 2, 3]);
Person.call(foo, 1, 2, 3);
콜백함수 내부의 this를 콜백함수를 호출하는 함수 내부의 this와 일치시켜줄 때 아래와 같이 사용된다.
function Person(name) {
this.name = name;
}
Person.prototype.doSomething = function (callback) {
if (typeof callback == 'function') {
callback.call(this); // call을 사용하지 않으면 foo에서 this는 window가 된다.
}
};
function foo() {
console.log(this.name);
}
var p = new Person('Lee');
p.doSomething(foo); // 'Lee'
인자로 전달한 this가 바인딩된 새로운 함수를 리턴한다.
let user = {
firstName: "John"
};
function func() {
console.log(this.firstName);
}
let funcUser = func.bind(user);
funcUser(); // John
한번 bind를 적용하면 bind를 사용하여 다시 정의할 수 없다.
function f() {
console.log(this.name);
}
f = f.bind( {name: "John"} ).bind( {name: "Ann" } );
f(); // John
참고
자바스크립트의 기본
함수 바인딩