function foo() {
x = 10;
}
foo();
console.log(x);
자바스크립트 엔진은 x 변수가 어디에서 선언되었는지 확인하기 위해 스코프 체인을 통해 검색한다.
먼저, 자바스크립트 엔진은 foo 함수의 스코프에서 x 변수의 선언을 찾을 것이다. 하지만, 값의 할당만 있을 뿐 변수 선언은 없기 때문에 상위 스코프로 넘어간다.
상위 스코프인 전역 스코프에서 x 변수의 선언을 검색한다. 역시 전역 스코프에서도 x 변수 선언이 존재하지 않기 때문에 ReferenceError를 발생시킬 것으로 예상된다.
하지만, 결과는 10이 나온다.
자바스크립트 엔진은 암묵적으로 전역 객체에 x 프로퍼티를 동적으로 생성한다. 이를 암묵적 전역(implicit global) 이라고 한다.
암묵적 전역은 개발자의 의도와 상관없는 오류를 발생시킬 수 있기 때문에 반드시 let, const와 같은 키워드를 사용해서 변수를 선언해야 한다.
하지만, 사람은 누구나 실수할 수 있다. 실수를 방지하기 위해 ES5부터 strict mode가 추가되었다.
strict mode는 자바스크립트 언어의 문법을 좀 더 엄격히 적용하여 오류를 발생시킬 가능성이 높거나 자바스크립트 엔진의 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다.
- 최근에는 ESLint 같은 린트 도구를 사용해 strict mode와 유사한 효과를 얻을 수 있다.
- 린트 도구는 정적 분석 기능을 통해 소스코드를 실행하기 전에 문법적 오류뿐만 아니라 잠재적 오류까지 찾아내고 오류의 원인을 알려주는 유용한 도구다.
'use strict';
function foo() {
x = 10;
}
foo();
// 결과
"Uncaught ReferenceError: x is not defined"
<script>
x = 1;
console.log(x);
</script>
<script>
'use strict';
y = 1;
console.log(y)
</script>
(function () {
'use strict';
}());
(function () {
var let = 10;
function foo() {
'use strict';
// SyntaxError: Unexpected strict mode reserved word
let = 20;
}
}());
(function () {
'use strict';
x = 1;
console.log(x); // ReferenceError: x is not defined
}());
(function () {
'use strict';
var x = 1;
// SyntaxError: Delete of an unqualified identifier in strict mode
delete x;
function foo(a) {
// SyntaxError: Delete of an unqualified identifier in strict mode
delete a;
}
// SyntaxError: Delete of an unqualified identifier in strict mode
delete foo;
}());
- delete 연산자는 객체의 속성을 삭제
- delete 연산자는 메모리를 직접 해제하는 것과 관련 없다.
delete object.property delete object['property']
- 성공적으로 객체에서 특정 속성을 제거하면 true를 반환, 그렇지 않으면 false 반환
- 삭제하려는 속성이 존재하지 않으면 true 반환
var nameOther = 'XYZ'; // 다음을 사용하여이 전역 속성에 액세스 할 수 있습니다. Object.getOwnPropertyDescriptor(window, 'nameOther'); // 출력 : Object {value : "XYZ", // 쓰기 가능 : true, // 열거 가능 : true, // 구성 가능 : false} // "nameOther"는 // var 키워드, "구성 할 수 없음"으로 표시됨 delete nameOther; // false 반환
(function () {
'use strict';
// SyntaxError: Duplicate parameter name not allowed in this context
function foo(x, x) {
return x + x;
}
console.log(foo(1, 2));
}());
var user = {
name: "unikys",
homepage: "unikys.tistory.com",
language: "Korean"
}
with (user) {
console.log(name === "unikys");
console.log(homepage === "unikys.tistory.com");
console.log(language === "Korean");
language = "javascript";
}
console.log(user.language === "javascript");
- eval, with는 사용하지 말자
- eval - 보안상, 퍼포먼스상 문제 존재
- with - 퍼포먼스, 모호성 문제 존재
function doSomething(value, obj) { with (obj) { value = "which scope is this?"; console.log(value); } }
(function (a) {
'use strict';
a = 2;
console.log(arguments); // { 0: 1, length: 1 }
}(1));