etc./StackOverFlow

"let"과 "var"를 사용하는 것의 차이점은 무엇입니까?

청렴결백한 만능 재주꾼 2021. 9. 25. 02:02
반응형

질문자 :TM.


ECMAScript 6 let 문을 도입했습니다.

local 변수로 설명되어 있다고 들었지만 var 키워드와 어떻게 다르게 동작하는지 아직 잘 모르겠습니다.

차이점은 무엇입니까? 언제 let 대신 var 사용해야 합니까?



답변자 : Community Wiki


범위 지정 규칙

주요 차이점은 범위 지정 규칙입니다. var 키워드로 선언된 변수는 즉시 함수 본문(따라서 함수 범위)으로 범위가 지정되는 let { } (따라서 블록 범위)로 표시된 직접 둘러싸는 블록으로 범위가 지정됩니다.

 function run() { var foo = "Foo"; let bar = "Bar"; console.log(foo, bar); // Foo Bar { var moo = "Mooo" let baz = "Bazz"; console.log(moo, baz); // Mooo Bazz } console.log(moo); // Mooo console.log(baz); // ReferenceError } run();

let 키워드가 언어에 도입된 이유는 함수 범위가 혼란스럽고 JavaScript의 주요 버그 소스 중 하나였습니다.

다른 stackoverflow 질문 에서 이 예를 살펴보세요.

 var funcs = []; // let's create 3 functions for (var i = 0; i < 3; i++) { // and store them in funcs funcs[i] = function() { // each should log its value. console.log("My value: " + i); }; } for (var j = 0; j < 3; j++) { // and now let's run each one to see funcs[j](); }

My value: 3 은 매번 funcs[j](); 익명 함수가 동일한 변수에 바인딩되었기 때문에 호출되었습니다.

사람들은 루프에서 올바른 값을 캡처하기 위해 즉시 호출되는 함수를 만들어야 했지만 이 역시 번거로웠습니다.

게양

var 키워드로 선언된 변수 가 호이스트 undefined 초기화됨) 이는 선언되기 전에도 둘러싸는 범위에서 액세스할 수 있음을 의미합니다.

 function run() { console.log(foo); // undefined var foo = "Foo"; console.log(foo); // Foo } run();

let 변수는 정의가 평가될 때까지 초기화되지 않습니다. 초기화 전에 액세스하면 ReferenceError 합니다. 블록의 시작부터 초기화가 처리될 때까지 "시간적 사각지대"에 있다고 하는 변수입니다.

 function checkHoisting() { console.log(foo); // ReferenceError let foo = "Foo"; console.log(foo); // Foo } checkHoisting();

전역 객체 속성 생성

최상위 수준에서 let var 와 달리 전역 객체에 속성을 생성하지 않습니다.

 var foo = "Foo"; // globally scoped let bar = "Bar"; // not allowed to be globally scoped console.log(window.foo); // Foo console.log(window.bar); // undefined

재선언

엄격 모드에서 var 를 사용하면 동일한 범위에서 동일한 변수를 다시 선언할 let 있고 let은 SyntaxError를 발생시킵니다.

 'use strict'; var foo = "foo1"; var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'. let bar = "bar1"; let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared



답변자 : Gurpreet Singh


let 은 클로저 문제를 피하기 위해 사용될 수도 있습니다. 아래 예와 같이 오래된 참조를 유지하는 대신 새로운 값을 바인딩합니다.

 for(var i=1; i<6; i++) { $("#div" + i).click(function () { console.log(i); }); }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <p>Clicking on each number will log to console:</p> <div id="div1">1</div> <div id="div2">2</div> <div id="div3">3</div> <div id="div4">4</div> <div id="div5">5</div>

위의 코드는 고전적인 JavaScript 클로저 문제를 보여줍니다. 받는 참조 i 변수 클릭 처리기 폐쇄 아닌 실제 값에 저장되고 i .

모든 단일 클릭 핸들러는 동일한 개체를 참조할 것입니다. 왜냐하면 6을 보유하는 카운터 개체가 하나뿐이므로 클릭할 때마다 6을 얻을 수 있기 때문입니다.

일반적인 해결 방법은 이것을 익명 함수로 래핑하고 i 를 인수로 전달하는 것입니다. 이러한 문제는 이제 아래 코드와 같이 let 대신 var 를 사용하여 피할 수도 있습니다.

(Chrome 및 Firefox 50에서 테스트됨)

 for(let i=1; i<6; i++) { $("#div" + i).click(function () { console.log(i); }); }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <p>Clicking on each number will log to console:</p> <div id="div1">1</div> <div id="div2">2</div> <div id="div3">3</div> <div id="div4">4</div> <div id="div5">5</div>



답변자 : John Slegers


letvar 의 차이점은 무엇인가요?

  • var 문을 사용하여 정의된 변수 는 함수 시작부터 정의된 함수 전체에 걸쳐 알려져 있습니다. (*)
  • let 문을 사용하여 정의된 변수는 정의된 순간부터 그것이 정의된 블록 에서만 알 수 있습니다. (**)

차이점을 이해하려면 다음 코드를 고려하십시오.

 // i IS NOT known here // j IS NOT known here // k IS known here, but undefined // l IS NOT known here function loop(arr) { // i IS known here, but undefined // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here for( var i = 0; i < arr.length; i++ ) { // i IS known here, and has a value // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here }; // i IS known here, and has a value // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here for( let j = 0; j < arr.length; j++ ) { // i IS known here, and has a value // j IS known here, and has a value // k IS known here, but has a value only the second time loop is called // l IS NOT known here }; // i IS known here, and has a value // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here } loop([1,2,3,4]); for( var k = 0; k < arr.length; k++ ) { // i IS NOT known here // j IS NOT known here // k IS known here, and has a value // l IS NOT known here }; for( let l = 0; l < arr.length; l++ ) { // i IS NOT known here // j IS NOT known here // k IS known here, and has a value // l IS known here, and has a value }; loop([1,2,3,4]); // i IS NOT known here // j IS NOT known here // k IS known here, and has a value // l IS NOT known here

여기서 변수 j 는 첫 번째 for 루프에서만 알려져 있지만 전후에는 알 수 없습니다. 그러나 우리의 변수 i 는 전체 함수에서 알려져 있습니다.

또한, 블록 범위 변수는 호이스팅되지 않기 때문에 선언되기 전에 알 수 없다는 점을 고려하십시오. 또한 동일한 블록 내에서 동일한 블록 범위 변수를 다시 선언할 수 없습니다. 이것은 블록 범위 변수가 호이스트되고 다중 선언의 경우 오류를 생성하지 않는 전역 또는 기능 범위 변수보다 오류 발생 가능성이 적습니다.


오늘 let 을 사용해도 안전한가요?

어떤 사람들은 미래에는 let 문만 사용할 것이며 var 문은 쓸모없게 될 것이라고 주장할 것입니다. JavaScript 전문가 Kyle Simpson왜 그렇게 되지 않을 것이라고 생각하는지에 대해 매우 정교한 기사를 작성했습니다.

그러나 오늘날에는 그렇지 않습니다. let 문을 사용하는 것이 안전한지 스스로에게 물어볼 필요가 있습니다. 해당 질문에 대한 답변은 환경에 따라 다릅니다.

  • 서버 측 JavaScript 코드( Node.js let 문을 안전하게 사용할 수 있습니다.

  • 클라이언트 측 JavaScript 코드를 작성하고 브라우저 기반 변환기(예: Traceur 또는 babel-standalone )를 사용하는 경우 let 문을 안전하게 사용할 수 있지만 코드는 성능 면에서 최적이 아닐 수 있습니다.

  • 클라이언트 측 JavaScript 코드를 작성하고 Node 기반 변환기(예: traceur 셸 스크립트 또는 Babel )를 사용하는 경우 let 문을 안전하게 사용할 수 있습니다. 그리고 브라우저는 트랜스파일된 코드에 대해서만 알기 때문에 성능상의 단점은 제한되어야 합니다.

  • 클라이언트 측 JavaScript 코드를 작성 중이고 변환기를 사용하지 않는 경우 브라우저 지원을 고려해야 합니다.

    let 을 전혀 지원하지 않는 브라우저가 여전히 있습니다.

여기에 이미지 설명 입력


브라우저 지원을 추적하는 방법

이 답변을 읽는 시점에 let 문을 지원하는지에 대한 최신 개요는 Can I Use 페이지를 참조하십시오 .


(*) 전역 및 기능 범위 변수는 JavaScript 변수가 호이스트 되기 때문에 선언되기 전에 초기화 및 사용할 수 있습니다. 이것은 선언이 항상 범위의 맨 위에 있음을 의미합니다.

(**) 블록 범위 변수는 호이스팅되지 않습니다.



답변자 : Ben S


다음은 몇 가지 예와 함께 let 키워드에 대한 설명입니다.

let var 와 매우 유사하게 작동합니다. 주요 차이점은 var 변수의 범위가 전체를 둘러싸는 함수라는 것입니다.

Wikipedia의 이 표 는 Javascript 1.7을 지원하는 브라우저를 보여줍니다.

Mozilla 및 Chrome 브라우저만 지원합니다. IE, Safari 및 잠재적으로 다른 사람들은 그렇지 않습니다.



답변자 : Lcf.vs


허용된 답변에 요점이 누락되었습니다.

 { let a = 123; }; console.log(a); // ReferenceError: a is not defined


답변자 : Michał Perłakowski


let

차단 범위

let 키워드를 사용하여 선언된 변수는 블록 범위입니다. 즉, 선언된 블록에서만 사용할 수 있습니다.

최상위 수준에서(함수 외부)

let 사용하여 선언된 변수는 전역 개체에 속성을 생성하지 않습니다.

 var globalVariable = 42; let blockScopedVariable = 43; console.log(globalVariable); // 42 console.log(blockScopedVariable); // 43 console.log(this.globalVariable); // 42 console.log(this.blockScopedVariable); // undefined

함수 내부

함수 내부(그러나 블록 외부)에서 let var 와 동일한 범위를 갖습니다.

 (() => { var functionScopedVariable = 42; let blockScopedVariable = 43; console.log(functionScopedVariable); // 42 console.log(blockScopedVariable); // 43 })(); console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

블록 내부

let 사용하여 선언된 변수는 해당 블록 외부에서 액세스할 수 없습니다.

 { var globalVariable = 42; let blockScopedVariable = 43; console.log(globalVariable); // 42 console.log(blockScopedVariable); // 43 } console.log(globalVariable); // 42 console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

루프 내부

let in 루프로 선언된 변수는 해당 루프 내에서만 참조할 수 있습니다.

 for (var i = 0; i < 3; i++) { var j = i * 2; } console.log(i); // 3 console.log(j); // 4 for (let k = 0; k < 3; k++) { let l = k * 2; } console.log(typeof k); // undefined console.log(typeof l); // undefined // Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.

클로저가 있는 루프

var 대신 let 을 사용하면 반복할 때마다 새 변수를 얻습니다. 즉, 루프 내에서 클로저를 안전하게 사용할 수 있습니다.

 // Logs 3 thrice, not what we meant. for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // Logs 0, 1 and 2, as expected. for (let j = 0; j < 3; j++) { setTimeout(() => console.log(j), 0); }

일시적인 데드존

시간적 사각지대 때문에 let 을 사용하여 선언된 변수는 선언되기 전에 액세스할 수 없습니다. 그렇게 하려고 하면 오류가 발생합니다.

 console.log(noTDZ); // undefined var noTDZ = 43; console.log(hasTDZ); // ReferenceError: hasTDZ is not defined let hasTDZ = 42;

재선언 불가

let 사용하여 동일한 변수를 여러 번 선언할 수 없습니다. var 사용하여 선언된 다른 변수와 동일한 식별자를 가진 let 을 사용하여 변수를 선언할 수 없습니다.

 var a; var a; // Works fine. let b; let b; // SyntaxError: Identifier 'b' has already been declared var c; let c; // SyntaxError: Identifier 'c' has already been declared

const

const let 과 매우 유사합니다. 블록 범위이며 TDZ가 있습니다. 그러나 두 가지 다른 점이 있습니다.

재할당 없음

const 를 사용하여 선언된 변수는 다시 할당할 수 없습니다.

 const a = 42; a = 43; // TypeError: Assignment to constant variable.

값을 변경할 수 없다는 의미는 아닙니다. 속성은 계속 변경할 수 있습니다.

 const obj = {}; obj.a = 42; console.log(obj.a); // 42

불변 객체를 갖고 싶다면 Object.freeze() 를 사용해야 합니다.

초기화가 필요합니다

const 사용하여 변수를 선언할 때 항상 값을 지정해야 합니다.

 const a; // SyntaxError: Missing initializer in const declaration


답변자 : Hasan Sefa Ozalp


가장 기본적인 용어로,

 for (let i = 0; i < 5; i++) { // i accessible ✔️ } // i not accessible ❌

 for (var i = 0; i < 5; i++) { // i accessible ✔️ } // i accessible ✔️

⚡️ 샌드박스에서 놀기 ↓

let 대 var 편집



답변자 : vlio20


다음은 이 둘의 차이점에 대한 예입니다(크롬 지원이 막 시작됨).
여기에 이미지 설명 입력

보시다시피 var j 변수는 여전히 for 루프 범위(블록 범위) 외부의 값을 가지고 있지만 let i 변수는 for 루프 범위 외부에서 정의되지 않습니다.

 "use strict"; console.log("var:"); for (var j = 0; j < 2; j++) { console.log(j); } console.log(j); console.log("let:"); for (let i = 0; i < 2; i++) { console.log(i); } console.log(i);



답변자 : Alireza


주요 차이점은 범위의 차이입니다. let 은 선언된 범위 내에서만 사용할 수 있지만 for 루프와 같이 var 는 루프 외부에서 액세스할 수 있습니다. MDN의 문서( MDN의 예도 포함)에서:

let을 사용하면 변수가 사용되는 블록, 명령문 또는 표현식으로 범위가 제한된 변수를 선언할 수 있습니다. 이것은 변수를 전역적으로 정의하거나 블록 범위에 관계없이 전체 함수에 대해 로컬로 정의하는 var 키워드와 다릅니다.

let에 의해 선언된 변수는 정의된 블록과 포함된 모든 하위 블록을 범위로 갖습니다. 이런 식으로 let 은 var 와 매우 유사하게 작동합니다. 주요 차이점은 var 변수의 범위가 전체 둘러싸는 함수라는 것입니다.

 function varTest() { var x = 1; if (true) { var x = 2; // same variable! console.log(x); // 2 } console.log(x); // 2 } function letTest() { let x = 1; if (true) { let x = 2; // different variable console.log(x); // 2 } console.log(x); // 1 }`

프로그램 및 함수의 최상위 수준에서 let 은 var 와 달리 전역 객체에 속성을 생성하지 않습니다. 예를 들어:

 var x = 'global'; let y = 'global'; console.log(this.x); // "global" console.log(this.y); // undefined

블록 내에서 사용될 때 let은 변수의 범위를 해당 블록으로 제한합니다. 범위가 선언된 함수 내부에 있는 var 의 차이점에 유의하십시오.

 var a = 1; var b = 2; if (a === 1) { var a = 11; // the scope is global let b = 22; // the scope is inside the if-block console.log(a); // 11 console.log(b); // 22 } console.log(a); // 11 console.log(b); // 2

또한 ECMA6 기능이라는 것을 잊지 마십시오. 아직 완전히 지원되지 않으므로 항상 Babel 등을 사용하여 ECMA5로 변환하는 것이 좋습니다. babel 웹사이트 방문에 대한 자세한 내용은



답변자 : olliej


미묘한 차이가 있습니다 - let 변수 범위 지정이 다소 다른 언어에서와 더 같이 범위 지정 동작합니다은.

예를 들어 엔클로징 블록으로 범위가 지정되고 선언되기 전에는 존재하지 않습니다.

let 은 최신 Javascript 구현의 일부일 뿐이며 다양한 수준의 브라우저 지원을 제공 한다는 점은 주목할 가치가 있습니다.



답변자 : zangw


  • 게양되지 않는 변수

    let 은 그들이 나타나는 블록의 전체 범위로 호이스트되지 않습니다 var 는 아래와 같이 호이스트될 수 있습니다.

     { console.log(cc); // undefined. Caused by hoisting var cc = 23; } { console.log(bb); // ReferenceError: bb is not defined let bb = 23; }

    실제로 @Bergi에 따르면 varlet 은 모두 hoisted입니다.

  • 쓰레기 수거

    let 블록 범위는 메모리 회수를 위한 클로저 및 가비지 수집과 관련하여 유용합니다. 고려하다,

     function process(data) { //... } var hugeData = { .. }; process(hugeData); var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });

    click hugeData 변수가 전혀 필요하지 않습니다. 이론적으로 process(..) 가 실행된 후에는 거대한 데이터 구조인 hugeData 가 가비지 수집될 수 있습니다. click 기능이 전체 범위에 대해 클로저를 가지고 있기 때문에 일부 JS 엔진은 여전히 이 거대한 구조를 유지해야 할 수도 있습니다.

    그러나 블록 범위는 이 거대한 데이터 구조를 가비지 수집으로 만들 수 있습니다.

     function process(data) { //... } { // anything declared inside this block can be garbage collected let hugeData = { .. }; process(hugeData); } var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });
  • let 루프

    let in 루프는 루프의 각 반복에 다시 바인딩할 수 있으므로 이전 루프 반복의 끝에서 값을 다시 할당해야 합니다. 고려하다,

     // print '5' 5 times for (var i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); }

    그러나 varlet

     // print 1, 2, 3, 4, 5. now for (let i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); }

    때문에 let )) 각각의 반복을 initialiser 표현 B를 A의 그 이름을 가진 새로운 어휘 환경을 조성 (와 previosly 증가 표현)을 평가하는 자세한 내용은 여기 .



답변자 : mormegil


차이점은 각각으로 선언된 변수 의 범위에 있습니다.

실제로 범위의 차이로 인해 다음과 같은 유용한 결과가 많이 있습니다.

  1. let 변수는 가장 가까운 블록( { ... } )에서만 볼 수 있습니다.
  2. let 변수는 변수가 선언된 후에 발생하는 코드 라인에서만 사용할 수 있습니다 (호이스팅된 경우에도!).
  3. let var 또는 let 의해 다시 선언되지 않을 수 있습니다.
  4. 전역 let 변수는 전역 window 개체에 추가되지 않습니다.
  5. let 변수는 클로저와 함께 사용하기 쉽습니다 (경합 조건을 일으키지 않음).

let 에 의해 부과된 제한은 변수의 가시성을 줄이고 예기치 않은 이름 충돌이 조기에 발견될 가능성을 높입니다. 이렇게 하면 도달 가능성 (사용하지 않는 메모리 회수에 도움)을 포함하여 변수를 더 쉽게 추적하고 추론할 수 있습니다.

결과적으로 let 변수는 대규모 프로그램에서 사용되거나 독립적으로 개발된 프레임워크가 새롭고 예상치 못한 방식으로 결합될 때 문제를 일으킬 가능성이 적습니다.

var 는 루프에서 클로저를 사용할 때(#5) 또는 코드에서 외부에서 볼 수 있는 전역 변수를 선언할 때(#4) 단일 바인딩 효과를 원하는 경우 여전히 유용할 수 있습니다. export 가 트랜스파일러 공간에서 코어 언어로 마이그레이션되는 var 사용이 대체될 수 있습니다.

1. 가장 가까운 둘러싸는 블록 외부에서 사용 금지: 이 코드 블록은 참조 오류를 발생시킵니다. x let 으로 선언된 블록 외부에서 발생하기 때문입니다.

 { let x = 1; } console.log(`x is ${x}`); // ReferenceError during parsing: "x is not defined".

var 를 사용한 동일한 예제가 작동합니다.

2. 선언 전 사용 금지:
이 코드 블록은 x 가 선언되기 전에 사용되기 때문에 코드를 실행하기 전에 ReferenceError

 { x = x + 1; // ReferenceError during parsing: "x is not defined". let x; console.log(`x is ${x}`); // Never runs. }

var 있는 동일한 예제는 예외를 던지지 않고 구문 분석하고 실행합니다.

3. 재선언 안 함: let 선언된 변수가 나중에 재선언되지 않을 수 있음을 보여줍니다.

 let x = 1; let x = 2; // SyntaxError: Identifier 'x' has already been declared

window 붙지 않은 전역:

 var button = "I cause accidents because my name is too common."; let link = "Though my name is common, I am harder to access from other JS files."; console.log(link); // OK console.log(window.link); // undefined (GOOD!) console.log(window.button); // OK

5. 클로저와 함께 쉽게 사용: var 선언된 변수는 루프 내부의 클로저에서 잘 작동하지 않습니다. 다음은 다른 시점에서 i 가 갖는 일련의 값을 출력하는 간단한 루프입니다.

 for (let i = 0; i < 5; i++) { console.log(`i is ${i}`), 125/*ms*/); }

구체적으로 다음을 출력합니다.

 i is 0 i is 1 i is 2 i is 3 i is 4

JavaScript에서는 변수가 생성될 때보다 훨씬 나중에 변수를 사용하는 경우가 많습니다. setTimeout 전달된 클로저로 출력을 지연시켜 이것을 시연할 때:

 for (let i = 0; i < 5; i++) { setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/); }

let 하는 한 출력은 변경되지 않습니다. var i 대신 사용했다면:

 for (var i = 0; i < 5; i++) { setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/); }

... 루프는 예기치 않게 "i is 5"를 5번 출력합니다.

 i is 5 i is 5 i is 5 i is 5 i is 5


답변자 : abroz


다음은 다른 사람들이 이미 작성한 내용에 추가하는 예입니다. adderFunctions 를 만들고 싶다고 가정해 봅시다. 여기서 각 함수는 단일 Number 인수를 취하고 인수의 합계와 배열의 함수 인덱스를 반환합니다. var 키워드를 사용하여 루프로 adderFunctions 를 생성하려고 하면 누군가가 순진하게 예상하는 방식으로 작동하지 않을 것입니다.

 // An array of adder functions. var adderFunctions = []; for (var i = 0; i < 1000; i++) { // We want the function at index i to add the index to its argument. adderFunctions[i] = function(x) { // What is i bound to here? return x + i; }; } var add12 = adderFunctions[12]; // Uh oh. The function is bound to i in the outer scope, which is currently 1000. console.log(add12(8) === 20); // => false console.log(add12(8) === 1008); // => true console.log(i); // => 1000 // It gets worse. i = -8; console.log(add12(8) === 0); // => true

i 의 범위가 각 함수가 생성된 for 블록의 반복을 넘어 확장되기 때문에 원하는 함수 배열을 생성하지 않습니다. 그 대신, 루프의 끝에서, i 각 기능의 클로저를 지칭 i 모든 익명 함수 용 루프 (1000)의 끝에서의 값을 adderFunctions . 이것은 우리가 원했던 것이 아닙니다. 이제 정확히 동일한 동작을 가진 1000개의 서로 다른 함수 배열이 메모리에 있습니다. 그리고 이후에 i 값을 업데이트하면 돌연변이가 모든 adderFunctions 영향을 미칩니다.

let 키워드를 사용하여 다시 시도할 수 있습니다.

 // Let's try this again. // NOTE: We're using another ES6 keyword, const, for values that won't // be reassigned. const and let have similar scoping behavior. const adderFunctions = []; for (let i = 0; i < 1000; i++) { // NOTE: We're using the newer arrow function syntax this time, but // using the "function(x) { ..." syntax from the previous example // here would not change the behavior shown. adderFunctions[i] = x => x + i; } const add12 = adderFunctions[12]; // Yay! The behavior is as expected. console.log(add12(8) === 20); // => true // i's scope doesn't extend outside the for loop. console.log(i); // => ReferenceError: i is not defined

이번에 for 루프가 반복될 때마다 i 이제 각 함수는 함수 생성 시 i adderFunctions 는 예상대로 작동합니다.

이제 두 가지 동작을 혼합한 이미지를 보면 동일한 스크립트에서 letconst 를 이전 var 와 혼합하는 것이 권장되지 않는 이유를 알 수 있습니다. 그렇게 하면 매우 혼란스러운 코드가 생성될 수 있습니다.

 const doubleAdderFunctions = []; for (var i = 0; i < 1000; i++) { const j = i; doubleAdderFunctions[i] = x => x + i + j; } const add18 = doubleAdderFunctions[9]; const add24 = doubleAdderFunctions[12]; // It's not fun debugging situations like this, especially when the // code is more complex than in this example. console.log(add18(24) === 42); // => false console.log(add24(18) === 42); // => false console.log(add18(24) === add24(18)); // => false console.log(add18(24) === 2018); // => false console.log(add24(18) === 2018); // => false console.log(add18(24) === 1033); // => true console.log(add24(18) === 1030); // => true

당신에게 이런 일이 일어나지 않도록하십시오. 린터를 사용하십시오.

참고: 이것은 루프 및 이해하기 쉬운 함수 클로저에서 var / let 동작을 보여주기 위한 교육 예제입니다. 이것은 숫자를 추가하는 끔찍한 방법이 될 것입니다. 그러나 익명 함수 클로저에서 데이터를 캡처하는 일반적인 기술은 다른 컨텍스트에서 실제 세계에서 발생할 수 있습니다. YMMV.



답변자 : Abdennour TOUMI


다음 두 함수가 차이점을 보여주기를 바랍니다.

 function varTest() { var x = 31; if (true) { var x = 71; // Same variable! console.log(x); // 71 } console.log(x); // 71 } function letTest() { let x = 31; if (true) { let x = 71; // Different variable console.log(x); // 71 } console.log(x); // 31 }


답변자 : Dmitry


let 은 다음과 같은 작업을 허용하기 때문에 흥미롭습니다.

 (() => { var count = 0; for (let i = 0; i < 2; ++i) { for (let i = 0; i < 2; ++i) { for (let i = 0; i < 2; ++i) { console.log(count++); } } } })();

그 결과 [0, 7]이 계산됩니다.

반면

 (() => { var count = 0; for (var i = 0; i < 2; ++i) { for (var i = 0; i < 2; ++i) { for (var i = 0; i < 2; ++i) { console.log(count++); } } } })();

[0, 1]만 계산합니다.



답변자 : RDoc


또한 적어도 Visual Studio 2015, TypeScript 1.5에서 "var"는 블록에서 동일한 변수 이름의 다중 선언을 허용하고 "let"은 허용하지 않는 것으로 보입니다.

컴파일 오류가 발생하지 않습니다.

 var x = 1; var x = 2;

이렇게 하면:

 let x = 1; let x = 2;


답변자 : Willem van der Veen


기능 대 블록 범위:

var와 let 의 주요 차이점은 var 선언된 var함수 범위라는 것 입니다. let 으로 선언된 함수 는 블록 범위 입니다. 예를 들어:

 function testVar () { if(true) { var foo = 'foo'; } console.log(foo); } testVar(); // logs 'foo' function testLet () { if(true) { let bar = 'bar'; } console.log(bar); } testLet(); // reference error // bar is scoped to the block of the if statement

var 변수:

첫 번째 함수 testVar var 선언된 변수 foo를 if 문 외부에서 계속 액세스할 수 있습니다. 이 변수 foo testVar 함수 범위 내의 모든 곳 에서 사용할 수 있습니다.

let 변수:

두 번째 함수 testLet let 선언된 변수 bar if 문 내에서만 액세스할 수 있습니다. let 으로 선언된 변수 는 블록 범위 이기 때문입니다(여기서 블록은 중괄호 사이의 코드입니다. 예를 들어 if{} , for{} , function{} ).

let 변수가 게양하지 않는다 :

varlet 또 다른 차이점은 let don't get hoisted 로 선언된 변수입니다. 다음은 이 동작을 설명하는 가장 좋은 방법입니다.

let don't get hoisted가 있는 변수:

 console.log(letVar); let letVar = 10; // referenceError, the variable doesn't get hoisted

var 있는 변수는 호이스트됩니다.

 console.log(varVar); var varVar = 10; // logs undefined, the variable gets hoisted

전역 let window 연결되지 않습니다.

let 으로 선언된 변수(함수에 없는 코드)는 전역 window 개체의 속성으로 추가되지 않습니다. 예를 들어(이 코드는 전역 범위에 있음):

 var bar = 5; let foo = 10; console.log(bar); // logs 5 console.log(foo); // logs 10 console.log(window.bar); // logs 5, variable added to window object console.log(window.foo); // logs undefined, variable not added to window object


언제 letvar 걸쳐 사용해야 합니까?

범위가 더 구체적이기 때문에 가능한 한 let over var 사용하십시오. 이렇게 하면 많은 수의 변수를 처리할 때 발생할 수 있는 잠재적인 이름 충돌이 줄어듭니다. var window 객체에 있기를 원할 때 사용할 수 있습니다(이것이 정말로 필요한 경우 항상 신중하게 고려하십시오).



답변자 : Srikrushna


ES6은 var를 대체하는 두 개의 새로운 키워드( letconst )를 도입했습니다.

블록 수준 감속이 필요할 때 var 대신 let 및 const를 사용할 수 있습니다.

아래 표에는 var, let 및 const의 차이점이 요약되어 있습니다.

여기에 이미지 설명 입력



답변자 : Moslem Shahsavan


var 는 전역 범위(호이스트 가능) 변수입니다.

letconst 는 블록 범위입니다.

test.js

 { let l = 'let'; const c = 'const'; var v = 'var'; v2 = 'var 2'; } console.log(v, this.v); console.log(v2, this.v2); console.log(l); // ReferenceError: l is not defined console.log(c); // ReferenceError: c is not defined



답변자 : Ankur Soni


let

let 키워드는 변수 선언을 포함하는 블록(일반적으로 { .. } 쌍)의 범위에 변수 선언을 첨부합니다. 즉, let 은 변수 선언에 대한 모든 블록의 범위를 암시적으로 하이재킹합니다.

let 변수는 전역적으로 액세스할 수 없기 때문에 window

 function a(){ { // this is the Max Scope for let variable let x = 12; } console.log(x); } a(); // Uncaught ReferenceError: x is not defined

var

var 및 변수에는 함수 범위가 있습니다. 즉, 변수는 함수 외부가 아니라 함수 내부에서 유효합니다.

var 변수는 전역적으로 액세스할 수 없기 때문에 window

 function a(){ // this is the Max Scope for var variable { var x = 12; } console.log(x); } a(); // 12

더 알고 싶다면 아래를 계속 읽으십시오

범위에 대한 가장 유명한 인터뷰 질문 중 하나는 아래와 같이 letvar

let 사용할 때

 for (let i = 0; i < 10 ; i++) { setTimeout( function a() { console.log(i); //print 0 to 9, that is literally AWW!!! }, 100 * i); }

let 을 사용할 때 모든 루프 반복에 대해 변수의 범위가 지정되고 자체 복사본이 있기 때문입니다.

var 사용할 때

 for (var i = 0; i < 10 ; i++) { setTimeout( function a() { console.log(i); //print 10 times 10 }, 100 * i); }

var 를 사용할 때 모든 루프 반복에 대해 변수의 범위가 지정되고 공유 복사본이 있기 때문입니다.



답변자 : Daniel Sokolowski


내가 사양을 읽으면 바로 그때 let 고맙게도도 피하기에 활용할 수있는 기능을 호출 자기 개인 만 회원을 시뮬레이션하는 데 사용 - 어쩌면 만족 제외시켰다 - 실제 코드 보호 또는 다른 혜택을 추가하지 즉, 코드의 가독성을 감소 인기있는 디자인 패턴, 디버깅 복잡를 의미론에 대한 누군가의 욕망이므로 사용을 중지하십시오. /폭언

 var SomeConstructor; { let privateScope = {}; SomeConstructor = function SomeConstructor () { this.someProperty = "foo"; privateScope.hiddenProperty = "bar"; } SomeConstructor.prototype.showPublic = function () { console.log(this.someProperty); // foo } SomeConstructor.prototype.showPrivate = function () { console.log(privateScope.hiddenProperty); // bar } } var myInstance = new SomeConstructor(); myInstance.showPublic(); myInstance.showPrivate(); console.log(privateScope.hiddenProperty); // error

'개인 인터페이스 에뮬레이션 '을 참조하십시오.



답변자 : zloctb


let 사용한 몇 가지 해킹:

1.

 let statistics = [16, 170, 10]; let [age, height, grade] = statistics; console.log(height)

2.

 let x = 120, y = 12; [x, y] = [y, x]; console.log(`x: ${x} y: ${y}`);

삼.

 let node = { type: "Identifier", name: "foo" }; let { type, name, value } = node; console.log(type); // "Identifier" console.log(name); // "foo" console.log(value); // undefined let node = { type: "Identifier" }; let { type: localType, name: localName = "bar" } = node; console.log(localType); // "Identifier" console.log(localName); // "bar"

let 하여 Getter 및 Setter:

 let jar = { numberOfCookies: 10, get cookies() { return this.numberOfCookies; }, set cookies(value) { this.numberOfCookies = value; } }; console.log(jar.cookies) jar.cookies = 7; console.log(jar.cookies)


답변자 : Piklu Dey


다음은 범위에서 'let'과 'var'가 어떻게 다른지 보여줍니다.

 let gfoo = 123; if (true) { let gfoo = 456; } console.log(gfoo); // 123 var hfoo = 123; if (true) { var hfoo = 456; } console.log(hfoo); // 456

gfoo 으로 정의된 let 초기에 전역 범위 에 있으며 if clause 내에서 gfoo 다시 선언하면 범위가 변경 되고 해당 범위 내의 변수에 새 값이 할당될 때 전역 범위에 영향을 주지 않습니다.

var 에 의해 정의된 hfoo 는 처음에는 전역 범위 if clause 내에서 선언할 때 전역 범위 hfoo 를 고려하지만 var 를 사용하여 다시 선언했습니다. 그리고 값을 다시 할당하면 전역 범위 hfoo도 영향을 받는 것을 볼 수 있습니다. 이것이 주요 차이점입니다.



답변자 : Vipul Jain


let은 es6의 일부입니다. 이 기능은 차이점을 쉽게 설명합니다.

 function varTest() { var x = 1; if (true) { var x = 2; // same variable! console.log(x); // 2 } console.log(x); // 2 } function letTest() { let x = 1; if (true) { let x = 2; // different variable console.log(x); // 2 } console.log(x); // 1 }


답변자 : daCoda


하자 대 var. 범위 에 관한 모든 것입니다.

var 변수는 전역적 이며 기본적으로 어디에서나 액세스할 수 있는 반면 let 변수는 전역적이지 않으며 닫는 괄호가 변수를 죽일 때까지만 존재합니다.

아래 내 예를 보고 lion(let) 변수가 두 console.logs에서 어떻게 다르게 작동하는지 확인하십시오. 두 번째 console.log에서 범위를 벗어납니다.

 var cat = "cat"; let dog = "dog"; var animals = () => { var giraffe = "giraffe"; let lion = "lion"; console.log(cat); //will print 'cat'. console.log(dog); //will print 'dog', because dog was declared outside this function (like var cat). console.log(giraffe); //will print 'giraffe'. console.log(lion); //will print 'lion', as lion is within scope. } console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var). console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.


답변자 : N Randhawa


상술 한 바와 같이:

차이점은 범위입니다. var 는 가장 가까운 함수 블록 으로 범위가 지정되고 let 은 함수 블록보다 작을 수 있는 가장 가까운 둘러싸는 블록으로 범위가 지정됩니다. 블록 외부에 있으면 둘 다 전역적입니다. 예를 살펴보겠습니다.

예 1:

내 두 가지 예에는 myfunc 함수가 있습니다. myfunc myvar 변수가 포함되어 있습니다. 첫 번째 예에서 myvar 가 10( myvar==10 )인지 확인합니다. 그렇다면, 나는 변수 선언 agian myvar 사용 (지금은 두 myVar에 변수가을) var 키워드를 그것에게 새로운 값 (20)을 할당합니다. 다음 줄에서 내 콘솔에 값을 인쇄합니다. 조건부 블록 후에 내 콘솔 myvar 값을 다시 인쇄합니다. myfunc 의 출력을 보면 myvar 값은 20과 같습니다.

let 키워드

예 2: 두 번째 예에서는 조건부 블록에서 var let 키워드를 사용하여 myvar myfunc 호출하면 myvar=20myvar=10 이라는 두 가지 다른 출력을 얻습니다.

따라서 차이점은 매우 간단합니다. 즉, 범위입니다.



답변자 : swaraj patil


let 사용하여 명령문 블록에 변수 범위를 지정하는 것이 더 낫다고 생각합니다.

 function printnums() { // i is not accessible here for(let i = 0; i <10; i+=) { console.log(i); } // i is not accessible here // j is accessible here for(var j = 0; j <10; j++) { console.log(j); } // j is accessible here }

나는 사람들이 다른 언어, Java, C# 등과 같은 JavaScript에서 유사한 범위를 갖도록 여기에서 let을 사용하기 시작할 것이라고 생각합니다.

JavaScript의 범위 지정에 대한 명확한 이해가 없는 사람들은 이전에 실수를 했습니다.

let 사용한 호이스팅은 지원되지 않습니다.

이 접근 방식을 사용하면 JavaScript에 있는 오류가 제거됩니다.

더 잘 이해 하려면 ES6 In Depth: let 및 const 를 참조하세요.



답변자 : Daniel Viglione


이 모든 것에서 실행 컨텍스트가 중요하기 때문에 이 키워드를 실행 컨텍스트에 연결하고 싶습니다. 실행 컨텍스트에는 생성 단계와 실행 단계의 두 단계가 있습니다. 또한 각 실행 컨텍스트에는 변수 환경과 외부 환경(어휘 환경)이 있습니다.

실행 컨텍스트의 생성 단계 동안 var, let 및 const는 주어진 실행 컨텍스트의 변수 환경에서 정의되지 않은 값으로 메모리에 변수를 계속 저장합니다. 차이점은 실행 단계에 있습니다. 값이 할당되기 전에 var로 정의된 변수를 참조하면 정의되지 않습니다. 예외가 발생하지 않습니다.

그러나 선언될 때까지 let 또는 const로 선언된 변수를 참조할 수 없습니다. 선언되기 전에 사용하려고 하면 실행 컨텍스트의 실행 단계에서 예외가 발생합니다. 이제 실행 컨텍스트의 생성 단계에 따라 변수가 여전히 메모리에 있지만 엔진에서 사용을 허용하지 않습니다.

 function a(){ b; let b; } a(); > Uncaught ReferenceError: b is not defined

var로 정의된 변수를 사용하여 엔진이 현재 실행 컨텍스트의 변수 환경에서 변수를 찾을 수 없으면 범위 체인(외부 환경)으로 이동하여 변수에 대한 외부 환경의 변수 환경을 확인합니다. 거기에서 찾을 수 없으면 스코프 체인을 계속 검색합니다. let과 const는 그렇지 않습니다.

let의 두 번째 기능은 블록 범위를 도입한다는 것입니다. 블록은 중괄호로 정의됩니다. 예제에는 펑션 블록, if 블록, for 블록 등이 포함됩니다. 블록 내부에 let으로 변수를 선언하면 변수는 블록 내부에서만 사용할 수 있습니다. 실제로 for 루프 내에서와 같이 블록이 실행될 때마다 메모리에 새 변수가 생성됩니다.

ES6은 또한 변수 선언을 위한 const 키워드를 도입했습니다. const도 블록 범위입니다. let과 const의 차이점은 const 변수는 이니셜라이저를 사용하여 선언해야 하며 그렇지 않으면 오류가 발생한다는 것입니다.

그리고 마지막으로 Execution Context의 경우 var로 정의된 변수가 'this' 객체에 붙는다. 전역 실행 컨텍스트에서는 브라우저의 창 개체가 됩니다. let이나 const의 경우는 그렇지 않습니다.



답변자 : Lucian Nut


저는 현재 JavaScript에 대한 심층적인 이해를 얻으려고 노력하고 있기 때문에 이미 논의된 몇 가지 훌륭한 부분과 다른 관점에서 다른 세부 사항이 포함된 간략한 연구를 공유할 것입니다.

functionblock scope 의 차이점을 이해한다면 varlet 의 차이점을 이해하는 것이 더 쉬울 수 있습니다.

다음과 같은 경우를 생각해 보자.

 (function timer() { for(var i = 0; i <= 5; i++) { setTimeout(function notime() { console.log(i); }, i * 1000); } })(); Stack VariableEnvironment //one VariablEnvironment for timer(); // when the timer is out - the value will be the same value for each call 5. [setTimeout, i] [i=5] 4. [setTimeout, i] 3. [setTimeout, i] 2. [setTimeout, i] 1. [setTimeout, i] 0. [setTimeout, i] #################### (function timer() { for (let i = 0; i <= 5; i++) { setTimeout(function notime() { console.log(i); }, i * 1000); } })(); Stack LexicalEnvironment - each iteration has a new lexical environment 5. [setTimeout, i] [i=5] LexicalEnvironment 4. [setTimeout, i] [i=4] LexicalEnvironment 3. [setTimeout, i] [i=3] LexicalEnvironment 2. [setTimeout, i] [i=2] LexicalEnvironment 1. [setTimeout, i] [i=1] LexicalEnvironment 0. [setTimeout, i] [i=0]

timer() 가 호출되면 각 반복에 해당하는 VariableEnvironment 와 모든 LexicalEnvironment를 모두 포함하는 ExecutionContext 가 생성됩니다.

그리고 더 간단한 예

기능 범위

 function test() { for(var z = 0; z < 69; z++) { //todo } //z is visible outside the loop }

블록 범위

 function test() { for(let z = 0; z < 69; z++) { //todo } //z is not defined :( }


답변자 : Sarvar Nishonboyev


나는 새로운 변수를 도입하기 위해 let 보다 var 를 사용해야 하는 한 가지 사용 사례를 발견했습니다. 다음은 사례입니다.

동적 변수 이름으로 새 변수를 만들고 싶습니다.

 let variableName = 'a'; eval("let " + variableName + '= 10;'); console.log(a); // this doesn't work
 var variableName = 'a'; eval("var " + variableName + '= 10;'); console.log(a); // this works

eval 이 새로운 코드 블록을 도입하기 때문에 위의 코드는 작동하지 않습니다. 사용 선언 var 때문에 코드 블록의 변수를 선언 할 외부 var 기능 영역에서 변수를 선언한다.

let 은 블록 범위에서 변수를 선언합니다. 그래서, 변수는에 표시됩니다 a eval 블록.



출처 : Here


출처 : http:www.stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var">

반응형