Web前端入门第 56 问:JavaScript 变量声明 var、let、const 区别
<p>曾经 <code>var</code> 如帝王一般统治过 JS 的变量声明,直到后来大佬们实在是忍不了 <code>var</code> 那稀烂的声明规则,便引入了 <code>let</code> 和 <code>const</code> 这两大刀斧手,<code>var</code> 被轻轻松松的斩落马下,如今,再难看见 <code>var</code> 的身影。</p><h2 id="变量声明">变量声明</h2>
<p>在 JS 中,所有变量都可以用 <code>var</code>、<code>let</code> 和 <code>const</code> 这三个关键字声明。</p>
<pre><code class="language-js">// 字符串
var name1 = '前端路引';
let name2 = '前端路引';
const name3 = '前端路引';
// 数字
var age1 = 18;
let age2 = 18;
const age3 = 18;
// 布尔值
var isDev1 = true;
let isDev2 = true;
const isDev3 = true;
// 空值
var null1 = null;
let null2 = null;
const null3 = null;
// 数组
var arr1 = ;
let arr2 = ;
const arr3 = ;
// 对象
var obj1 = {};
let obj2 = {};
const obj3 = {};
// 函数
var fn1 = function () {
console.log('前端路引');
}
let fn2 = function () {};
const fn3 = function () {};
</code></pre>
<p>以上的各种声明方法都是有效的,JS 语法也没强制要求必须用某个关键字声明变量。</p>
<h2 id="区别">区别</h2>
<p>它们之间有哪些恩恩怨怨,为什么会在新的语法中引入 <code>let</code> 和 <code>const</code> 来取代 <code>var</code> 呢?</p>
<h3 id="作用域">作用域</h3>
<p>var 申明的变量,拥有函数作用域,在整个函数体内部都能访问。</p>
<p>let 和 const 申明的变量是块级作用域,出了代码块(就是 <code>{}</code> 包裹的代码片段)就不可以再访问了。</p>
<pre><code class="language-js">function funcScope() {
if (true) {
var a = 1; // 函数作用域
let b = 2; // 块级作用域
const c = 3; // 块级作用域
}
console.log(a); // 1(var 穿透了 if 代码块)
console.log(b); // ReferenceError: b is not defined
console.log(c); // ReferenceError: c is not defined
}
</code></pre>
<h3 id="变量申明提升">变量申明提升</h3>
<p>var 申明的变量,不论在哪个位置申明,都会提升到作用域顶部。</p>
<p>let 和 const 申明存在 <code>暂时性死区(TDZ)</code>,这些名词道道记不住也罢,反正您只要知道在申明之前使用会报错就对了。</p>
<pre><code class="language-js">console.log(x); // undefined(变量提升)
var x = 10;
console.log(x); // 10
console.log(y); // ReferenceError: y is not defined(暂时性死区)
let y = 20;
</code></pre>
<p>var 申明的变量,在申明之前使用会获取 <code>undefined</code>,这就是所谓的 <code>变量申明提升</code>。</p>
<h3 id="重复声明">重复声明</h3>
<p>var 允许同一个变量重复声明。</p>
<p>let 和 const 禁止重复声明。</p>
<pre><code class="language-js">var a = 1;
var a = 2; // 允许
console.log(a) // 2
let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared
const c = 1;
const c = 2; // SyntaxError: Identifier 'c' has already been declared
</code></pre>
<p>let 和 const 重复声明同一个变量,会报语法错误。</p>
<h3 id="全局作用域下的行为">全局作用域下的行为</h3>
<p>如果在全局作用域中使用 var 申明一个变量,那么这变量会变成全局对象(如 window)的一个属性。</p>
<p>let 和 const 则不会绑定到全局对象。</p>
<p>什么是全局作用域?比如新建一个 a.js,使用 <code><script src="a.js"></script></code> 引入这个 JS 文件到 html 页面中,那么这个 JS 文件最外层就称之为全局作用域。</p>
<p><strong>新建一个 test.html,引入 a.js:</strong></p>
<pre><code class="language-html"><script src="a.js"></script>
</code></pre>
<p><strong>新建一个 a.js:</strong></p>
<pre><code class="language-js">// 全局作用域
var globalVar = 1;
console.log(window.globalVar); // 1
let globalLet = 2;
console.log(window.globalLet); // undefined
function test () {
// 函数作用域
};
{
// 块级作用域
}
</code></pre>
<h3 id="可变性">可变性</h3>
<p>var 和 let 声明的变量可以重新赋值。</p>
<p>const 声明的是常量,必须初始化且不可重新赋值(但对象/数组的内容可修改)。</p>
<pre><code class="language-js">var str = '前端路引';
str = 'web3dev'; // 允许修改变量
let num = 1;
num = 2; // 允许修改变量
const PI = 3.14;
PI = 3; // TypeError: Assignment to constant variable.(不可重新赋值)
const obj = { a: 1 };
obj.a = 2; // 允许(修改属性)
obj = {}; // TypeError: Assignment to constant variable.(不可重新赋值)
</code></pre>
<p>为什么 const 申明的数组和对象可以修改?</p>
<p>这就涉及到 <code>引用</code> 这个概念了,可以理解为 <code>数组</code> 和 <code>对象</code> 就像现实中的房子。const 申明就像给房子打上了标签贴,拥有了这个房子的使用权,但这房子不止 const 一个拥有者,房子的主人还能对房子进行室内装修改变。const 的标签贴只能使用一次,要想把这标签再贴在另一座房子,那么就行不通了!!</p>
<h3 id="循环">循环</h3>
<p>var 申明的变量会泄露到循环体外部。</p>
<p>let 仅作用于循环体内部。</p>
<pre><code class="language-js">for (var i = 0; i < 3; i++) {}
console.log(i); // 3
for (let j = 0; j < 3; j++) {}
console.log(j); // ReferenceError: j is not defined
</code></pre>
<p>let 解决异步回调问题:</p>
<pre><code class="language-js">// var 的问题
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 输出 3, 3, 3
}
// let 的解决方案
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j)); // 输出 0, 1, 2
}
</code></pre>
<h2 id="写在最后">写在最后</h2>
<p>最佳实践推荐:所有变量声明优先考虑使用 <code>const</code> ,如果确定变量需要修改再使用 <code>let</code>。</p>
<p>果您的代码确实需要兼容 2017 年之前的浏览器,那么使用 <code>var</code> 吧,别考虑 <code>const</code> 和 <code>let</code> 了。当然也可以使用 <code>babel</code> 等编译器,将 <code>const</code> 和 <code>let</code> 转换成 <code>var</code> 兼容低版本浏览器。</p>
</div>
<div id="MySignature" role="contentinfo">
<p> </p>
<p style="font-size: 18px;font-weight: bold;">文章首发于微信公众号【<span style="color:rgb(255, 71, 87)">前端路引</span>】,欢迎 <span style="color:#4ec259">微信扫一扫</span> 查看更多文章。</p>
<p>
<img style="max-width: 320px;" src="https://images.cnblogs.com/cnblogs_com/linx/2447020/o_250228035031_%E5%85%AC%E4%BC%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png"/>
</p>
<p>本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/18888666</p>
<p> </p><br><br>
来源:https://www.cnblogs.com/linx/p/18888666
頁:
[1]