
함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.
단, 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
참고
자바스크립트의 기본
함수 바인딩