“let”과 “var”의 차이점은 무엇입니까?

ECMAScript 6은 이 문구를 도입하였다.

로컬 변수로 기술되어 있다고 들었습니다만, var 키워드와 어떻게 다른지 아직 잘 모르겠습니다.

어떤 차이가 있을까?언제가 좋습니까?let대신 사용되다var?



질문에 대한 답변



범위 지정 규칙

주요 차이점은 범위 지정 규칙입니다.선언한 변수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키워드는 함수의 범위가 혼란스러워서 자바스크립트의 버그의 주요 원인 중 하나였기 때문에 이 언어에 도입되었습니다.

다른 스택 오버플로우 질문에서 다음 예를 보겠습니다.

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

리클라레이션

strict 모드에서는var같은 범위 내에서 동일한 변수를 재지정할 수 있습니다.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




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을 유지하는 카운터 객체는 1개뿐이므로 클릭할 때마다 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>




와의 차이는 무엇입니까?let그리고.var?

  • 를 사용하여 정의된 변수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는 첫 번째 루프에서만 인식되며 이전과 이후는 인식되지 않습니다.하지만 우리의 변수는i는 기능 전체에 알려져 있습니다.

또한 블럭 범위 변수는 중단되지 않기 때문에 선언되기 전에 알 수 없는 것으로 간주하십시오.또한 동일한 블록 범위 변수를 동일한 블록 내에서 다시 선언할 수 없습니다.따라서 블록 범위 변수는 글로벌 또는 기능 범위 변수보다 오류가 발생하기 쉬우며, 여러 선언이 있더라도 오류가 발생하지 않습니다.


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

어떤 사람들은 미래에는 let 스테이트먼트만 사용할 것이며 var 스테이트먼트는 쓸모없게 될 것이라고 주장할 것이다.JavaScript의 권위자인 Kyle Simpson은 왜 그렇지 않을 것이라고 믿는지에 대해 매우 정교한 기사를 썼다.

그러나 오늘날에는 절대 그렇지 않다.사실, 우리는 실제로 우리 자신에게 이 기술을 사용하는 것이 안전한지 자문해 볼 필요가 있다.let진술.이 질문에 대한 답변은 환경에 따라 달라집니다.

  • 서버측 JavaScript 코드(Node.js)를 작성하는 경우,let진술.

  • 클라이언트 측 JavaScript 코드를 작성하고 브라우저 기반 트랜스필러(Traceur 또는 babel-standalone 등)를 사용하는 경우 안전하게let스테이트먼트. 단, 퍼포먼스에 관해서는 코드가 최적이 아닐 수 있습니다.

  • 클라이언트 측 JavaScript 코드를 작성하고 노드 기반 트랜스필러(traceur스크립트 또는 Babel 등)를 사용하는 경우 안전하게let진술.또한 브라우저는 변환된 코드만 인식하므로 성능 단점은 제한되어야 합니다.

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

    아직 지원하지 않는 브라우저가 있습니다.let전혀:

enter image description here


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

지원되는 브라우저의 최신 개요는let이 답변을 읽을 때의 스테이트먼트는, 이 페이지참조해 주세요.


(*) JavaScript 변수가 호이스트되기 때문에 글로벌 및 기능 범위 변수를 선언하기 전에 초기화하고 사용할 수 있습니다.즉, 선언은 항상 스코프의 최상위에 있습니다.

(**) Block Scope 변수가 hoe되지 않음




다음은 키워드에 대한 설명과 몇 가지 예를 제시하겠습니다.

let와 매우 유사하다var. 주요 차이점은 의 범위가varvariable은 둘러싸는 함수 전체입니다.

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

Mozilla 및 Chrome 브라우저만 지원됩니다.IE, Safari 및 기타 기능에서는 지원되지 않을 수 있습니다.




승인된 답변에는 요점이 누락되어 있습니다.

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