변수 선언 사이에 차이점이 있습니까?
var a=0; //1
...이 방법:
a=0; //2
...또는:
window.a=0; //3
글로벌 범위에서?
변수 선언 사이에 차이점이 있습니까?
var a=0; //1
...이 방법:
a=0; //2
...또는:
window.a=0; //3
글로벌 범위에서?
답변:
그렇습니다. 몇 가지 차이점이 있지만 실제로는 큰 차이가 없습니다.
네 번째 방법이 있으며 ES2015 (ES6) 기준으로 두 가지가 더 있습니다. 마지막에 네 번째 방법을 추가했지만 # 1 뒤에 ES2015 방법을 삽입 했으므로 이유를 알 수 있습니다.
var a = 0; // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4
#1 var a = 0;
이것은 또한의 한 속성입니다 전역 변수 생성 전역 객체 우리가 접근, window
브라우저에서을 (또는 통해 this
비 엄격한 코드의 글로벌 범위). 다른 속성과 달리 속성을 통해 제거 할 수 없습니다 delete
.
사양 측면에서, 그것은 생성 바인딩 식별자 상의 객체 환경 기록 에 대한 지구 환경을 . 전역 객체는 전역 환경의 객체 환경 레코드에 대한 식별자 바인딩이 유지되는 위치이므로 전역 객체의 속성이됩니다. 이것이 속성이 삭제 불가능한 이유입니다. 단순한 속성이 아니라 식별자 바인딩입니다.
바인딩 (변수)은 첫 번째 코드 행이 실행되기 전에 정의됩니다 (아래의 "언제 var
발생"참조).
주에 생성 된 속성은 IE8에 이전하는 것이 window
아닙니다 열거 (에 표시되지 않는 for..in
문). IE9, Chrome, Firefox 및 Opera에서는 열거 가능합니다.
# 1.1 let a = 0;
이것은 전역 객체의 속성 이 아닌 전역 변수를 만듭니다 . 이것은 ES2015에서 새로운 것입니다.
스펙 용어로, 환경 레코드 오브젝트가 아닌 글로벌 환경 에 대한 선언적 환경 레코드 에서 ID 바인딩을 작성합니다 . 글로벌 환경은 분할 환경 기록, 글로벌 객체 (이게 오래된 물건 모두를위한 하나의 필요에 고유 한 개체 새로운 물건 모두를위한 환경 기록) 및 다른 ( , ,과에 의해 생성 된 기능 )하지 전역 객체로 이동하십시오.let
const
class
바인딩 생성 포위 블록의 모든 단계별 코드 (전역 코드가 실행되기 전에,이 경우)을 실행하기 전에, 그러나 아니다 접근 단계별 실행이 도달 할 때까지 어떤 방법으로 let
문을. 실행이 let
명령문에 도달하면 변수에 액세스 할 수 있습니다. ( "참조 let
및 const
아래 발생".)
# 1.2 const a = 0;
글로벌 상수를 작성합니다. 글로벌 상수는 글로벌 오브젝트의 특성이 아닙니다.
const
정확히처럼 let
당신이 초기화합니다 (제공해야한다는 점을 제외하고 = value
일부)하고,이 생성 된 후에는 당신이 상수의 값을 변경할 수 없습니다. 표지 아래에서 let
와 동일 하지만 식별자 바인딩에 값을 변경할 수 없다는 플래그가 있습니다. 사용 const
은 세 가지 일을합니다.
# 2 a = 0;
이것은 전역 객체에 대한 속성을 암시 적 으로 만듭니다 . 일반적인 속성이므로 삭제할 수 있습니다. 나는 이것을 하지 않는 것이 좋습니다 . 나중에 코드를 읽는 사람에게는 분명하지 않을 수 있습니다. ES5의 엄격 모드를 사용하는 경우, 존재하지 않는 변수에 할당하는 것은 오류입니다. 엄격 모드를 사용하는 몇 가지 이유 중 하나입니다.
그리고 흥미롭게도 IE8 및 이전 버전에서는 속성을 열거 할 수 없습니다 ( for..in
구문 에는 표시되지 않음 ). 특히 아래 # 3에 나오는 것은 이상합니다.
#삼 window.a = 0;
이렇게하면 전역 객체 window
를 참조 하는 전역을 사용하여 전역 객체에 대한 속성이 명시 적으로 생성 됩니다 (브라우저에서, 브라우저가 아닌 일부 환경에는 global
NodeJS 와 같은 전역 변수가 있습니다 ). 일반적인 속성이므로 삭제할 수 있습니다.
이 속성 은 IE8 및 이전 버전과 내가 시도한 다른 모든 브라우저에서 열거 가능합니다.
# 4 this.a = 0;
global this
대신에 전역 객체를 참조한다는 점을 제외하고는 # 3과 정확히 같습니다 window
. 엄격 모드 전역 코드에서는 this
전역 객체에 대한 참조가 없기 때문에 엄격 모드에서는 작동하지 않습니다 ( undefined
대신 값이 있음 ).
"삭제"또는 "제거"는 무엇을 의미 a
합니까? 정확히 : delete
키워드 를 통해 속성을 완전히 제거하십시오 .
window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
delete
객체에서 속성을 완전히 제거합니다. 당신은 속성에 추가로 그렇게 할 수 없습니다 window
를 통해 간접적으로 var
는이 delete
중 하나를 자동으로 무시하거나 (자바 스크립트 구현에 당신이 엄격 모드에있어 여부에 따라) 예외가 발생합니다.
경고 : IE8 다시 (그리고 아마도 이전 버전과 깨진 "호환성"모드에서 IE9-IE11) : window
허용되어 있어도 객체의 속성을 삭제할 수 없습니다 . 더 나쁜 것은 IE8 및 다른 브라우저 에서이 실험 을 시도 하면 예외가 발생합니다 . 따라서 객체 에서 삭제할 때는 방어 적이어야합니다.window
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
속성을 삭제하려고 시도하고 예외가 발생하면 다음으로 최선을 다하고 속성을로 설정합니다 undefined
.
이것은 객체 에만 적용되며 window
IE8 및 이전 버전 (또는 깨진 "호환성"모드의 IE9-IE11) 에만 적용됩니다 . 다른 브라우저는 window
위 규칙에 따라 속성 을 삭제 해도됩니다.
var
발생비아 정의 된 변수 var
전에 문은 생성 된 모든 실행 컨텍스트에서 단계별로 코드가 실행되고, 그래서 속성이 아니라 존재 하기 전에var
문.
혼란 스러울 수 있으므로 살펴 보겠습니다.
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
라이브 예 :
보다시피, 심볼 foo
은 첫 번째 라인 전에 정의되지만 심볼 bar
은 그렇지 않습니다. 를 Where var foo = "f";
문이 두 가지 정말이 있습니다 : 실행되는 코드의 첫 번째 행 앞에 일어나는 기호, 정의는; 및 라인이 단계별 흐름 내에있는 경우, 그 심볼에 할당을 수행하는 단계를 포함한다. 파트가 스코프 상단으로 이동 ( " var
호이 스팅" var foo
) 되었으나 foo = "f"
파트가 원래 위치에 남아 있기 때문에 " 게양"이라고합니다 . ( 빈약 한 작은 블로그에서 잘못 이해var
한 가난한 사람을 참조하십시오 .)
let
그리고 const
어떻게let
과 const
는 다른 var
몇 가지 방법입니다. 질문과 관련된 방법은 정의한 바인딩이 단계별 코드가 실행되기 전에 생성되지만 또는 문에 도달 할 때까지 액세스 할 수 없다는 것 입니다.let
const
그래서 이것이 실행되는 동안 :
display(a); // undefined
var a = 0;
display(a); // 0
오류가 발생합니다.
display(a); // ReferenceError: a is not defined
let a = 0;
display(a);
다른 두 가지 방법이 있는지 let
와는 const
다를 var
질문에 정말 관련이없는 어떤이다 :
var
항상 (글로벌 코드 전체에, 또는이 표시되는 기능에 기능 코드를 통해) 전체 실행 컨텍스트에 적용되지만 let
및 const
단지 내에서 적용 블록 들이 나타납니다. 즉, var
함수 (또는 글로벌) 범위를 갖지만, let
및 const
블록의 범위를 갖는다.
var a
동일한 컨텍스트에서 반복 하는 것은 무해하지만 let a
(또는 const a
) let a
가 const a
있거나 다른 또는 a 또는 a var a
가있는 경우 구문 오류입니다.
여기에 있음을 보여주는 예입니다 let
및 const
그 블록이 실행 내에서 코드 전에 블록에 즉시 적용되지만까지 액세스 할 수 없습니다 let
또는 const
문 :
var a = 0;
console.log(a);
if (true)
{
console.log(a); // ReferenceError: a is not defined
let a = 1;
console.log(a);
}
두 번째 는 블록 외부에서 console.log
액세스하는 대신 실패합니다 a
.
window
)window
객체는 매우 속성 어수선하게됩니다. 가능하면 혼란에 추가하지 않는 것이 좋습니다. 대신에 약간의 패키지와 수출에 문자를 마무리 가장 받는 하나의 기호 window
객체입니다. (나는 자주 내 보내지 않습니다 어떤 받는 문자 window
당신은 당신의 문자하기 위해 모든 코드를 포함하는 함수를 사용할 수 있습니다. 개체), 그리고이 마음에 그 기능은 익명으로 할 수 있습니다 :
(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
이 예에서는 함수를 정의하고 바로 ()
끝까지 실행 합니다.
이런 방식으로 사용되는 함수를 범위 지정 함수 라고 합니다 . 범위 지정 함수 내에 정의 된 함수는 해당 데이터에 대한 폐쇄 이기 때문에 범위 지정 함수에 정의 된 변수에 액세스 할 수 있습니다 ( 폐쇄는 빈약 한 블로그에서 복잡하지 않습니다)를 참조하십시오 .
window['a']=0
이 내가지도로 창을 사용하고 취소 할 수 있나요? 입니다 window
일부 브라우저는이를 허용하고 사용하라고 강요하지 않는 특별 window.a
?
window.a = 0;
은 브라우저 환경에서만 작동하며 규칙에 의해서만 작동 한다는 것입니다 . 전역 객체를 이름 지정된 변수에 바인딩하는 window
것은 ES 사양에 없으므로 V8 또는 Node.js와 같이 작동하지 않지만 this.a = 0;
(전역 실행 컨텍스트에서 호출 된 경우) 사양 이 지정되어 있기 때문에 모든 환경에서 작동합니다. 가 있어야한다는 전역 객체. 에서 같은 인생에서 코드를 포장하는 경우 오프 주제 섹션, 당신은 통과 할 수 라는 이름의 매개 변수로 또는 전역 객체에 대한 직접 참조를 얻을 수 있습니다. this
window
global
var a = 0;
자동으로 전역 객체의 속성이됩니다. 내가 선언하면 var b = 0;
함수 선언 내에서, 또한 몇 가지 기본 객체의 속성이 될 것인가?
간단하게 유지 :
a = 0
위의 코드는 전역 범위 변수를 제공합니다
var a = 0;
이 코드는 현재 범위에서 사용되는 변수를 제공합니다.
window.a = 0;
이것은 일반적으로 전역 변수와 동일합니다.
a
에 따라 현재 범위. 할 수 있습니다. 또한 "전역 변수"를 사용하는 것은 약간의 문제입니다. "전역 변수"라고 말하는 두 곳은 말하지 않은 곳보다 더 전역 적이 지 않습니다.
<title>Index.html</title>
<script>
var varDeclaration = true;
noVarDeclaration = true;
window.hungOnWindow = true;
document.hungOnDocument = true;
</script>
<script src="external.js"></script>
/* external.js */
console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8
console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!) *I personally find this more clugy than hanging off window obj
기본적으로 모든 변수가 중단되는 전역 객체가 있습니까? 예 : 'globals.noVar 선언'
window.*
선언 사용에 대한 명확한 안내서 . 이 선언은 코드를 복사하여 붙여 넣는 것에 대해 가장 안전하고 명확합니다.
TJ Crowder 의 탁월한 답변을 바탕으로 : ( 주제 : 혼란을 피하십시오window
)
이것은 그의 아이디어의 예입니다.
HTML
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="init.js"></script>
<script type="text/javascript">
MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
</script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello !</h1>
</body>
</html>
init.js ( 이 답변을 기반으로 함 )
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {}; // private
return {
init : function(Args) {
_args = Args;
// some other initialising
},
helloWorld : function(i) {
return _args[i];
}
};
}());
script.js
// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);
alert(a);
다음은 plnkr 입니다. 그것이 도움이되기를 바랍니다!
전 세계적으로 의미 상 차이는 없습니다.
그러나 a=0
값을 선언되지 않은 변수로 설정하므로 실제로 피해야 합니다.
또한 전역 범위를 전혀 편집하지 않으려면 클로저를 사용하십시오.
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
항상 필요한 경우 클로저를 사용하고 항상 글로벌 범위로 호이스트하십시오. 어쨌든 대부분의 통신에 비동기 이벤트 처리를 사용해야합니다.
@AvianMoncellor가 언급했듯이 var a = foo
파일 범위에 대한 전역을 선언 하는 IE 버그가 있습니다. 이것은 IE의 악명 높은 깨진 통역사와 관련된 문제입니다. 이 버그는 친숙하게 들리므로 아마도 사실 일 것입니다.
그러니까 window.globalName = someLocalpointer
delete
var
var
. 그것들은 실질적으로 동일한 실제 결과를 갖는 완전히 다른 메커니즘입니다. :-)
var
범위의 멈춤으로 점프하는 것을 언급하는 것을 잊었다 .