-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
let、const、var 的区别有哪些? #16
Comments
const person = {
name: `zhang`
}
person.name = `yu`;
console.log(person.name); // `yu` |
let 和 const 都是块级声明的一种。
let 和 const 的区别: |
var的作用: let与const: 相同点: 异同点: |
let和const声明都在代码块内有效。不存在变量提升。相同作用域内,不能重复命名。 |
全局声明的var变量会挂载到window上,而let和const不会; |
let和const都是作用于代码块的声明,var 的作用域是当前 scope 的所有子作用域,包括当前作用域中声明或调用的函数或是 while / for / if / try-catch 语法区块。let和const都是es5,es6新版本的js语言规范出来的定义,在这以前定义一个变量只能用var。var存在变量提升,let,const不存在。let,const不允许重复声明同一变量,而var可以 |
var [ECMAScript 1st Edition (ECMA-262)规范]
let [ECMAScript 2015 (6th Edition, ECMA-262)规范]
const[ECMAScript 2015 (6th Edition, ECMA-262)规范]
|
|
var
let
const
|
|
|
1.变量提升var会进行变量提升,let和const不会进行提升 2.暂存死区因为var会进行变量提升,所以可以在声明之前访问,不会形成暂存死区。let 和const 不会进行变量提升,在声明之前不能使用,形成暂存死区 3.重复声明var可以进行重复声明,但是let和const不能进行重复声明 4.块作用域var不会形成块作用域,let和const可以形成块作用域 5.重新赋值var和let声明的变量可以重新赋值,const不可以。如果const 声明的变量存储的是引用地址, 是可以修改这个引用对应的对象的值的,但是这个变量不能被赋予其他值 |
|
let、const、var的区别有哪些?js本身只有全局作用域和函数作用域,let和const的出现,使得js有了块级作用域。 for(var i = 0; i < 10; i++) {
}
console.log(i) // 10
for(let j = 0; j < 10; j++) {
}
console.log(j) // Uncaught ReferenceError: j is not defined |
let 和 const都是ES6新增的
比如上面这个例子,已经不在for循环中了,已经跳出这个块了,我们还是能打印出
let的出现让变量拥有块级作用域,把上面的 我们总结一下var ,let, const 的区别
let
const
2.暂时性死区
3.重复声明
//报错
//报错
//不报错 4.重新赋值 var和let可以重新赋值,但是const不可以,而且const 必须声明的时候就初始化。 |
|
console.log(a) // 打印的是undefined
var a = 10
console.log(b) // 直接报错
let b = 10
console.log(c) // 直接报错
const c = 10
{
var a = 10
}
console.log(a) // 10
{
let b = 10
}
console.log(a) // 直接报错 b 未定义
{
const c = 10
}
console.log(c) // 和let一样
{
let a = 100;
a = 10;
console.log(a) // 10
}
{
const b; // 直接报错
console.log(b)
const c = 10;
c = 100 ;// 直接报错
} |
let、const是ES6声明变量的方式,与var相比:
let、const对比
|
|
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i) // 0,1,2 如果用var 打印出来就是333
}, 1000);
}
3. const定义常量(申明时必须有初始值),let定义变量,两者不存在变量提升,先申明在使用,而且不能重复申明 |
if (true) {
const MAX = 5;
let a = 10;
var b = 1;
MAX // 5
a // 10
b // 1
}
MAX // Uncaught ReferenceError: MAX is not defined
a // ReferenceError: a is not defined.
b // 1
let foo;
let foo; // TypeError thrown.
ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
const foo;
// SyntaxError: Missing initializer in const declaration
// 对于const来说,只声明不赋值,就会报错。 let 和 const 作为 ES6 新增的命令,相较 var 有更多的特性,更多内容可以点击下面链接查看: |
1,什么时候提出的?var是ES5提出的,let和const是ES6提出的。 2,是否存在变量提升?var声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为undefined。 3,是否存在暂时性死区?let和const存在暂时性死区。即只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。 4,是否允许重复声明变量?var允许重复声明变量。let和const在同一作用域不允许重复声明变量。 5,是否存在块级作用域?var不存在块级作用域。let和const存在块级作用域。 6,是否能修改声明的变量?var和let可以。 |
let 局部作用域变量,有暂时性死区特性 |
let const 是es6引入的新的语法。 |
1、var声明的变量会存在变量提升,let和const不存在变量提升 |
var 和 let 用来声明变量,const 只能声明一个只读的常量 |
let和const |
复习下MDN
|
var,let声明变量,const声明常量,var能重复声明 |
首先var,let,const都是定义变量的方式, |
let、const、var 的区别有哪些?let、var的区别?
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。
const 与 let、var的区别?
最后附上: |
let const 与 var 的区别let
const
var
|
下面看一道经典的例子
改成
三次setTimeout 的回调共享同一变量,循环结束的时候i为3,let 就是解决这个问题 |
|
变量提升var 声明的变量存在变量提升,也就是说 var 声明的变量可以在声明之前使用; 重复声明var 命令可以重复声明同名变量,然后覆盖掉之前声明的变量; 声明时赋值,修改var 和 let 命令在声明变量时可以赋值,也可以不赋值,赋值后还可以修改; 块级作用域var 命令声明的变量不存在块级作用域,即在大括号 { } 中声明会变量提升到当前作用域(全局作用域或函数作用域)的头部; |
es5中只有全局作用域和函数作用域,并没有块级作用域,因此在es6中就增加了 let和const两个命令来改善var的一些不合理,不严谨的地方。下面我就就进行一一的对比,比较一些他们之间的区别 (step-by-step)
- 作用域是块级作用域
- let不允许在同一作用域内重复声明同一个变量
- 存在暂时性死区
const 命令
那么如果使用const声明对象呢?
我们可以看到,使用const声明的对象的属性是可以修改。 因为Object类型是引用类型。用const声明常量保存的是对象的地址,不可变的是地址,在上面的代码中就是,不能把 b指向另一个对象。而修改对象的属性,并不会改变对象的地址,因此用const声明对象的属性是可以修改的 |
1.let/const 定义的变量不会出现变量提升,而 var 定义的变量会提升。a = 10;
var a; //正常 a = 10;
let a; //ReferenceError 2.let 和 const 不允许重复声明,var 允许重复声明。let a = 10;
var a = 20;
//抛出异常:SyntaxError: Identifier 'a' has already been declared 3.const 声明一个只读的常量,这个常量不可改变。const声明变量时必须赋值。这里有一个非常重要的点即是:复杂数据类型,存储在栈中的是堆内存的地址,存在栈中的这个地址是不变的,但是存在堆中的值是可以变得。有没有相当常量指针/指针常量~ const a = 20;
const b = {
age: 18,
star: 500
} 一图胜万言,如下图所示,不变的是栈内存中 a 存储的 10,和 b 中存储的 0x0012ff21(瞎编的一个数字)。而 {age: 18, star: 200} 是可变的。思考下如果想希望一个对象是不可变的,应该用什么方法? 4.let/const 声明的变量仅在块级作用域中有效。而 var 声明的变量在块级作用域外仍能访问到。{
let a = 10;
const b = 20;
var c = 30;
}
console.log(a); //ReferenceError
console.log(b); //ReferenceError
console.log(c); //30 在 let/const 之前,最早学习JS的时候,也曾被下面这个问题困扰: var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10 虽然后来知道了为什么,但是想要得到自己需要的结果,还得整个闭包,我...我做错了什么,要这么对我... var a = [];
for (var i = 0; i < 10; i++) {
a[i] = (function(j){
return function () {
console.log(j);
}
})(i)
}
a[6](); // 6 有了 let 之后,终于不要这么麻烦了。 var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6 美滋滋,有没有~ 美是美了,但是总得问自己为什么吧~ 第一个 再看 let , 我们说 let 声明的变量仅在块级作用域内有效,变量i是let声明的,当前的 i 只在本轮循环有效,所以每一次循环的 i 其实都是一个新的变量。有兴趣的小伙伴可以使用看一下 babel 编译后的代码。 5.顶层作用域中 var 声明的变量挂在window上(浏览器环境)var a = 10;
console.log(window.a);//10 6.let/const有暂时性死区的问题,即let/const 声明的变量,在定义之前都是不可用的。如果使用会抛出错误。只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。 var a = 10;
if (true) {
a = 20; // ReferenceError
let a;
} 在代码块内,使用 let/const 命令声明变量之前,该变量都是不可用的,也就意味着 typeof 不再是一个百分百安全的操作。 console.log(typeof b);//undefined
console.log(a); //ReferenceError
let a = 10; |
let
{
let a = 1;
var b = 2;
}
console.log(a); // ReferenceError: a is not defined
console.log(b); // 2 不存在变量提升
console.log(a); // undefined
var a = 10;
console.log(b); // ReferenceError: b is not defined
let b = 20;
var a = 10;
let b = 20;
console.log(window.a); // 10
console.log(window.b) // undefined 暂时性死区只要块级作用域内存在 var a = 10;
if (true) {
console.log(a); // ReferenceError: a is not defined
let a;
} 上面代码中,虽然存在全局变量 不允许重复声明
function f1() {
let a = 10;
var a = 20;
}
f1();
// 报错:SyntaxError: Identifier 'a' has already been declared 因此,也不能在函数内部重复声明参数。 function f2(arg) {
let arg;
}
f2();
// 报错:SyntaxError: Identifier 'arg' has already been declared function f2(arg) {
{
let arg;
}
}
f2(); // 不报错 const
const PI = 3.1415;
PI; // 3.1415;
PI = 3;
// TypeError: Assignment to constant variable.
const a;
// SyntaxError: Missing initializer in const declaration
本质
对于简单类型的数据(数值、字符串、布尔值),值就保存在变量所指向的那个地址,因此等同于常量。 但对于复杂类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针, const obj = {};
// 为obj添加一个属性,可以成功
obj.prop = 10;
obj.prop; // 10
// 将obj指向另一个对象就会报错
obj = {}; // Assignment to constant variable. 看下数组的例子: const arr = [];
arr.push(1); // 可以执行
arr; // [1]
// 把另外一个数组赋值给它就会报错
arr = [2,3]; // Assignment to constant variable. 总结
|
最近在读<深入理解ES6>一书中,提起 let/const 这也是平常工作用的比较多,最近需要给公司做培训. 重新复习下以往的知识点. 本文首发自 github 个人博客. let/const再聊 var通过下面的例子, 可以复习下, 关键字 console.log(typeof A) // 'function'
console.log(a) // undefined
console.log(typeof a) // 'undefined'
console.log(typeof Date) // 'function'
console.log(window.Date) // function Date() {}
function A() {
console.log(new Date())
}
var a = 10
var Date = 1000
console.log(window.Date) // 1000 由于 同样的代码,把 由此可见
通常的习惯可能是, 放在 top scope 的位置, 作为一个规范来约束自己或团队. 但并不是每个人都能很好的按照规范来做, 于是ES6 推出了 let/const来解决 let/const把上面的代码换成 console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
console.log(typeof a) // 'undefined'
console.log(typeof Date) // 'function'
console.log(window.Date) // function Date() {} 之前执行的 直接运行 let a = 10
let Date = 1000
console.log(window.Date) // function Date() {}
console.log(a) // 10
console.log(Date) // 1000
console.log(window.a) // undefined 正常逻辑执行后, 并没有想象中, 暂时性死区(temporal dead zone, TDZ)在 let/const不会对 scope 域名做覆盖/污染上述例子中, 循环中形成新的块级绑定早年有一个经典的面试题, 叫做 创建10 个 div.点击输出对应的索引. 笔者在初次写 js 的时候, 写成了这种错误形式 // bad way
for(var i = 0; i < 10; i++) {
var div = document.createElement('div')
div.className = 'item'
div.innerHTML = i
div.onclick = function() {
alert(i)
}
document.body.appendChild(div)
} 输出的结果也往往是 10, 需求是点击索引啊. 造成这种结果的原因是 var变量提升, 当点击的时候此时 i 是 10 因此我们常常用 IIFE(即时执行函数) // good way
for(var i = 0; i < 10; i++) {
var div = document.createElement('div')
div.className = 'item'
div.innerHTML = i
div.onclick = (function(i) {
return function() {
alert(i)
}
})(i)
document.body.appendChild(div)
} 那有木有更好的方案, 能不能每次 循环的时候创建一个新的 i, // better way
for (let i = 0; i < 10; i++) {
let div = document.createElement("div");
div.className = "item";
div.innerHTML = i;
div.onclick = function() {
alert(i)
}
document.body.appendChild(div);
} 其他
关于对象的常量问题, 放到后面章节整理. |
let const不会存在变量提升,而var会存在变量提升。 |
let 、const、var的区别:
|
1、let是es6新增的声明变量的方式 |
1、var 变量作用域为函数作用域,可以提前声明,可以修改,如果使用未赋值的变量,默认未undefined;存在变量提升。 |
var 和let/const的区别: 以下注意两点; 第三;不存在变量提升 // let 的情况 第四;暂时性死区 |
let:存在变量提升 |
let和const不会变量提升,var会 const声明的对象,不可操作栈(重新初始化对象obj=123),但可以操作堆(对象属性赋值obj.name=123) |
1.不存在变量提升let和const不存在变量提升;例: 2.let 、const 声明存在块级作用域
3.不允许在同一作用域重复声明同一变量
4. 暂时性死区 在代码块内,使用let声明变量之前,该变量都是不可以使用;只要在同一作用域内存在let命令,它所声明的变量,就绑定在该作用域中,不管外部有没有声明此变量;例: |
let const var的区别 es5 提出了var 声明变量的方式 var let 与const 1.let 与const 都拥有块级作用域 什么是块级作用域? |
var 定义变量变量会提升,let const不会变量提升let 和 const 存在块级作用域 |
let、const、var 的区别有哪些?什么是提升?(hoisting)首先我们来看一段代码 console.log(变量) // undefined
var 变量 = 1 从上面的代码来看,虽然变量还没有被声明,但是我们却可以使用,这种情况就叫做提升,并且是声明提升。 再来一段代码 console.log(变量) // ƒ 变量() {}
function 变量() {}
var 变量 = 1 上面的代码叫做函数提升,函数提升跟变量提升差不多,就是函数提升优先级比变量高。 从上可知,使用 区别首先我们再来看一段代码 var a = 1
let b = 1
const c = 1
console.log(window.b) // undefined
console.log(window.c) // undefined
function test(){
console.log(a)
let a
}
test() 首先在全局作用域下使用 再者当我们在声明 首先报错的原因是因为存在暂时性死区,我们不能在声明前就使用变量,这也是 let、const、var 创建的不同
var语句声明了作用于 正在运行的执行上下文(running execution context) 的 变量环境(VariableEnvironment) 的变量。
|
var、let、const都是用来声明变量的。
|
let
constconst声明一个只读的常量,表示一旦使用const声明变量,就必须初始化。不能等到以后才赋值
var
|
(一)var
(二)let
(三)const
|
No description provided.
The text was updated successfully, but these errors were encountered: