Javascript (글로벌 변수 포함)의 변수 선언 구문의 차이점은 무엇입니까? 사이에 차이점이 있습니까? var

변수 선언 사이에 차이점이 있습니까?

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 바인딩을 작성합니다 . 글로벌 환경은 분할 환경 기록, 글로벌 객체 (이게 오래된 물건 모두를위한 하나의 필요에 고유 한 개체 새로운 물건 모두를위한 환경 기록) 및 다른 ( , ,과에 의해 생성 된 기능 )하지 전역 객체로 이동하십시오.letconstclass

바인딩 생성 포위 블록의 모든 단계별 코드 (전역 코드가 실행되기 전에,이 경우)을 실행하기 전에, 그러나 아니다 접근 단계별 실행이 도달 할 때까지 어떤 방법으로 let문을. 실행이 let명령문에 도달하면 변수에 액세스 할 수 있습니다. ( “참조 letconst아래 발생”.)


# 1.2 const a = 0;

글로벌 상수를 작성합니다. 글로벌 상수는 글로벌 오브젝트의 특성이 아닙니다.

const정확히처럼 let당신이 초기화합니다 (제공해야한다는 점을 제외하고 = value일부)하고,이 생성 된 후에는 당신이 상수의 값을 변경할 수 없습니다. 표지 아래에서 let와 동일 하지만 식별자 바인딩에 값을 변경할 수 없다는 플래그가 있습니다. 사용 const은 세 가지 일을합니다.

  1. 상수에 할당하려고하면 구문 분석 시간 오류가 발생합니다.
  2. 다른 프로그래머에게 변하지 않는 특성을 문서화합니다.
  3. JavaScript 엔진이 변경되지 않는 것을 기반으로 최적화하도록합니다.

# 2 a = 0;

이것은 전역 객체에 대한 속성을 암시 적 으로 만듭니다 . 일반적인 속성이므로 삭제할 수 있습니다. 나는 이것을 하지 않는 것이 좋습니다 . 나중에 코드를 읽는 사람에게는 분명하지 않을 수 있습니다. ES5의 엄격 모드를 사용하는 경우, 존재하지 않는 변수에 할당하는 것은 오류입니다. 엄격 모드를 사용하는 몇 가지 이유 중 하나입니다.

그리고 흥미롭게도 IE8 및 이전 버전에서는 속성을 열거 할 수 없습니다 ( for..in구문 에는 표시되지 않음 ). 특히 아래 # 3에 나오는 것은 이상합니다.


#삼 window.a = 0;

이렇게하면 전역 객체 window를 참조 하는 전역을 사용하여 전역 객체에 대한 속성이 명시 적으로 생성 됩니다 (브라우저에서, 브라우저가 아닌 일부 환경에는 globalNodeJS 와 같은 전역 변수가 있습니다 ). 일반적인 속성이므로 삭제할 수 있습니다.

이 속성 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.

이것은 객체 에만 적용되며 windowIE8 및 이전 버전 (또는 깨진 “호환성”모드의 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"

라이브 예 :

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"

function display(msg) {
  var p = document.createElement('p');
  p.innerHTML = msg;
  document.body.appendChild(p);
}

보다시피, 심볼 foo은 첫 번째 라인 전에 정의되지만 심볼 bar은 그렇지 않습니다. 를 Where var foo = "f";문이 두 가지 정말이 있습니다 : 실행되는 코드의 첫 번째 행 앞에 일어나는 기호, 정의는; 및 라인이 단계별 흐름 내에있는 경우, 그 심볼에 할당을 수행하는 단계를 포함한다. 파트가 스코프 상단으로 이동 ( ” var호이 스팅” var foo) 되었으나 foo = "f"파트가 원래 위치에 남아 있기 때문에 ” 게양”이라고합니다 . ( 빈약 한 작은 블로그에서 잘못 이해var가난한 사람을 참조하십시오 .)


언제 let그리고 const어떻게

letconst는 다른 var몇 가지 방법입니다. 질문과 관련된 방법은 정의한 바인딩이 단계별 코드가 실행되기 전에 생성되지만 또는 문에 도달 때까지 액세스 할 수 없다는 것 입니다.letconst

그래서 이것이 실행되는 동안 :

display(a);    // undefined
var a = 0;
display(a);    // 0

오류가 발생합니다.

display(a);    // ReferenceError: a is not defined
let a = 0;
display(a);

다른 두 가지 방법이 있는지 let와는 const다를 var질문에 정말 관련이없는 어떤이다 :

  1. var항상 (글로벌 코드 전체에, 또는이 표시되는 기능에 기능 코드를 통해) 전체 실행 컨텍스트에 적용되지만 letconst단지 내에서 적용 블록 들이 나타납니다. 즉, var함수 (또는 글로벌) 범위를 갖지만, letconst블록의 범위를 갖는다.

  2. var a동일한 컨텍스트에서 반복 하는 것은 무해하지만 let a(또는 const a) let aconst a있거나 다른 또는 a 또는 a var a가있는 경우 구문 오류입니다.

여기에 있음을 보여주는 예입니다 letconst그 블록이 실행 내에서 코드 전에 블록에 즉시 적용되지만까지 액세스 할 수 없습니다 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`
    }
})();

이 예에서는 함수를 정의하고 바로 ()끝까지 실행 합니다.

이런 방식으로 사용되는 함수를 범위 지정 함수 라고 합니다 . 범위 지정 함수 내에 정의 된 함수는 해당 데이터에 대한 폐쇄 이기 때문에 범위 지정 함수에 정의 된 변수에 액세스 할 수 있습니다 ( 폐쇄는 빈약 한 블로그에서 복잡하지 않습니다)를 참조하십시오 .


답변

간단하게 유지 :

a = 0

위의 코드는 전역 범위 변수를 제공합니다

var a = 0;

이 코드는 현재 범위에서 사용되는 변수를 제공합니다.

window.a = 0;

이것은 일반적으로 전역 변수와 동일합니다.


답변

<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 선언’


답변

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