var、、var、let、const 之间的区别
- var 声明的变量可以
重复声明,let、const不可以; - var 声明的变量会
提升到当前作用域的最前面,let、const不会; - var声明的变量会
挂载到window上,成为window的属性,let、const不会; - let、const会产生
块级作用域,var不会 - let、const存在
暂时性死区(声明之前不能调用),var没有
针对cosnt声明的变量: - cosnt 声明时,
必须赋值,否则会报错,
这是因为const声明的变量在初始化之后就不能再次赋值,因此必须在声明时赋值。 - cosnt声明的是常量,
不能更改,
指的是基本数据类型不能更改值,而引用数据类型不能更改他的引用地址,这意味着无法通过赋值语句来更改常量的值,但是如果const声明的变量是一个对象或数组,则仍然可以更改其属性或元素的值。
var 可以重复声明
如果在同一作用域中重复使用var关键字声明一个已经存在的变量名,后面的声明会覆盖前面的声明。
这是因为在JavaScript中,变量声明提升到了所在作用域的顶部,并且重复声明的变量名只是重新赋值给了同一个变量。因此,最终只有最后一次声明的变量保留了值。
如下,a在当前作用域声明了3次,但是只保留了a=111
var a=1
var a=3
var a=111
console.log(a)// 111
需要注意的是,虽然var可以重复声明,但不建议频繁地使用它来重复声明同一个变量,因为这可能会导致代码难以理解和维护
======================================>
let、const不能重复声明:
如果在同一作用域内用 let或const重复声明同一个变量名,就会抛出一个错误。这是因为JavaScript编译器在编译过程中会检查变量名是否已经存在于当前作用域中,如果存在,则会引发一个语法错误,以避免可能导致问题的重复定义。
let b=1
let b=3//抛出错误 Uncaught SyntaxError: Identifier 'b' has already been declared
const c=1
const c=2//Uncaught SyntaxError: Identifier 'c' has already been declared
不允许在同一作用域内重复声明同一个变量名,但const声明的变量必须在声明时进行初始化,而let则可以稍后进行赋值。
var变量声明的提升
在 JavaScript 中,使用 var 声明的变量会被提升到其所在作用域(全局作用域或函数作用域)顶部。这意味着无论变量声明在函数或全局作用域的任何位置,都会在代码执行前先预解析后执行。
例如,以下代码中的 console.log 语句可以正常输出变量 x 的值,尽管 x 的实际赋值语句在 console.log 之后:
function example() {
console.log(x); // 输出 undefined
var x = 1;
}
这是因为 JavaScript 引擎在代码执行前会对 example 函数进行预编译,将变量声明 var x; 提升到函数作用域顶部。在实际执行 console.log(x) 时,变量 x 已经在内存中被分配了空间,但还未被赋值,因此输出 undefined。
需要注意的是,虽然 var 声明的变量会被提升,但其赋值语句不会被提升。如果在变量声明前使用该变量,则其值将是 undefined。
==============================>
let和cosnt 变量的声明不会提升
在JavaScript中,使用let和const声明的变量也是存在作用域提升的行为的,但它们与var关键字声明不同的地方是:
- 声明的变量会被提升到当前块级作用域的顶部(而非全局或函数作用域中),这意味着变量在其声明语句之前是不可访问的。
- 在变量实际被声明之前,如果尝试访问该变量,则会引发“ReferenceError: Cannot access 'x' before initialization”错误,这个行为被称为“暂时性死区”(Temporal Dead Zone,缩写为TDZ)。
例如:
console.log(x); // Uncaught ReferenceError: Cannot access 'x' before initialization
let x = 10;
在这个例子中,如果我们尝试在 x 声明之前访问该变量,代码则会抛出“未初始化访问”的错误。在块级作用域内使用let和const定义的变量提升行为与这个示例类似。
var声明的变量,会挂载到window上
在浏览器环境下,使用var关键字声明的全局变量会自动成为全局对象 window 的一个属性。这意味着可以在全局作用域以外的任何地方访问和修改该变量,并且可以通过 window 对象来访问它。
例如:
var x = 10;
console.log(window.x); // 10
上述代码中,变量 x 被定义在全局作用域中,并且自动成为 window 对象的一个属性,因此在 window 对象中可以看到它的值为 10。
需要注意的是,在严格模式(strict mode)下,var声明的变量不会自动绑定到全局对象上,而是只存在于定义它的作用域内。建议在使用变量时显式引用其作用域而不是依赖全局状态。推荐使用let或const关键字来声明块级作用域变量,以避免出现全局污染和命名冲突的问题。
let、cosnt会生成块级作用域
在 JavaScript 中,let 和 const 声明的变量存在块级作用域。这意味着它们只在声明所在的代码块范围内有效,而不是像 var 那样在整个函数或全局作用域范围内有效。
例如,在以下代码中:
function block() {
if (true) {
let x = 1;
const y = 2;
console.log(x, y); // 输出 1 2
}
console.log(x, y); // 抛出 ReferenceError 错误
}
block();//调用函数
变量 x 和 y 的作用域被限制在了 if 代码块内部,在代码块外部的同名变量是无法访问的。这种行为被称为块级作用域。
=========>
var声明变量
function block() {
if (true) {
var x = 1;
var y = 1;
console.log(x,y); // 输出 1,2
}
console.log(x,y); // 输出1,2
}
block();
用var声明就不会把x限制在 if 代码块内部,在外部同样可以访问到x,y
使用 var 关键字声明的变量可以在作用域链中查找,如果该变量没有在当前作用域定义,JavaScript 引擎会向上遍历作用域链,直到找到该变量为止。如果该变量在最终的全局作用域中仍未找到,则会创建一个新的全局变量,并成为全局对象的一个属性。
这意味着,使用 var 声明的变量在函数内部或块级作用域内定义,也可以在函数之外或全局作用域中访问和修改,因为它们存在于共同的作用域链之中。
例如:
function fn() {
var x = 1;
}
fn();//调用函数fn
console.log(x); // 1
在这个例子中,变量 x 被定义在函数作用域内部,但在调用函数之后,我们依然可以在全局作用域访问它,并且获取到它被赋的值 10。
需要注意的是,在 ES6 中引入 let 和 const 关键字,它们声明的变量有块级作用域,并且不具备变量提升和在作用域之外被访问的特性。因此,最好遵循尽可能使用块级作用域的原则,并尽量避免在函数外部定义变量。
let、cosnt存在暂时性死区
et 和 const 关键字声明的变量存在“暂时性死区”(Temporal Dead Zone,缩写为TDZ)的概念。在作用域中,变量在被声明之前是不可访问的,如果尝试访问一个在其声明之前的变量,则会抛出 ReferenceError 错误。
例如:
console.log(a); // 抛出 ReferenceError 错误
let a = 100;
console.log(b); // 抛出 ReferenceError 错误
let = 100;
在上面的例子中,变量 a``b 的声明在访问之后,访问该变量就会触发“未定义”的引用错误。
这是因为在 JavaScript 引擎执行代码时,let 和 const 声明的变量会被放入一个临时的“死区”,在此期间变量无法被访问或修改,只有在赋值表达式之后,该变量才会从死区中移除并可正常使用。这种行为被称为“暂时性死区”。
const
cosnt 声明时,必须赋值
使用 const 关键字声明变量时必须要进行赋值操作,否则会抛出 SyntaxError 错误。
例如:
const x; // 抛出 SyntaxError 错误
当然,赋值的值可以是任何类型的数据,包括字面量、变量、函数表达式等等。一旦使用 const 声明了一个变量,该变量就不能再被重新赋值为其他不同的值。这意味着,在 const 变量的生命周期中,其指向的内存地址是不能被修改的,因此也被称为“常量”。
需要注意的是,使用 const 声明的变量并不代表它是不可变的。如果被定义为对象或数组(引用数据类型),我们可以更改对象或数组的属性和元素。只有它指向的内存地址不能发生改变。
cosnt声明后,不能更改
使用 const 关键字声明的变量被称为常量,它们的值在声明之后不能再次被修改。这意味着在给 const 常量赋值之后,它就不能被重新赋值为其他不同的值。
例如:
const x = 8;
x= 9; // 抛出 TypeError 错误
在这个例子中,尝试将常量 x 的值从 8 更改为 9 时会抛出类型错误。
相对应的,如果定义的是包含对象或数组的常量,则该对象和数组可以进行修改操作,但是常量指向的地址(引用)不能被修改,否则也会抛出类型错误。
例如:
const obj = {x: 1 };
obj.x = 2; // 可以修改,修改的引用地址指向的值
obj = { x: 3 }; // 抛出 TypeError 错误
在这个示例中,我们可以修改属性 x 的值,但是无法将 obj 重新分配为一个新的对象,因为这会改变 obj 的引用地址。
需要注意的是,在代码中使用 let 或 const 关键字声明块级作用域的变量,可以避免污染全局作用域并有助于减少命名冲突。所以,最好使用 const 声明那些预计不会被重新赋值的变量。