关于var
1.允许二次定义
var x = 10;console.log(x);//10
var x = 20;console.log(x);//20
2.存在变量提升
var x = 10;
function test(){
console.log(x);//undefined
var x = 10;
}
test();
3.变量提升个人理解
根据文章let深入理解的理解,变量创建步骤细分为:创建>初始化>赋值。
当调用test函数,进入一个执行环境,收集变量对象(变量,test函数内的函数),提升到该环境顶端,创建var定义的变量x,同时初始化为undefined。
所以var变量提升包括创建和初始化undefined。
4.污染全局作用域
for(var i =1;i<5;i++){}
console.log(window.i);//5
5.隐式变量不存在提升
console.log(a);//Uncaught ReferenceError: a is not defined
a = 'aaa';
关于let
1.存在块级作用域
{ let x = 10;} console.log(x);//x is not defined
2.暂时性死区
暂时性死区:变量必须先定义再使用。
var x =10;
function test(){
console.log(x);//Cannot access 'x' before initialization
let x = 20;
}
test();
3.暂时性死区理解,let存在变量提升吗?
打印x报错,提示想要访问x必须先初始化。
当调用test函数,进入一个执行环境,收集变量对象(变量,test函数内的函数),提升到该环境顶端,创建let定义的变量x,但let定义的变量只有[创建]阶段提升了,[初始化]阶段没提升,而没初始化就不给访问,报错。
所以还是存在提升的,只不过是[创建]阶段提升了。
4.let解决延迟打印问题
for(var i=1;i<5;i++){
setTimeout(()=>{
console.log(i);
},1000);
}//打印4个5
for(let i=1;i<5;i++){
setTimeout(()=>{
console.log(i);
},1000);
}//打印1 2 3 4
为什么出现这种情况?
for循环执行了4次,一共创造了4个执行环境,每个执行环境都有对应的i,但是var定义的i没有块级作用域的概念,所以i都是定义在全局上的,而let定义的i都是保存在块级作用域内的。
5.let,const不允许重复定义
{ let x = 5;let x = 10;}//Uncaught SyntaxError: Identifier 'x' has already been declared
{let x = 5;var x =10;}//Uncaught SyntaxError: Identifier 'x' has already been declared
{let x = 5;const x =10;}//Uncaught SyntaxError: Identifier 'x' has already been declared
{const x = 5;let x = 5}//Uncaught SyntaxError: Identifier 'x' has already been declared
关于const
1.const声明必须带着初始化
const x;
x = 5;
console.log(x);//Uncaught SyntaxError: Missing initializer in const declaration
2.const只能初始化一次
const x = 10;
x = 5;
console.log(x);//Uncaught TypeError: Assignment to constant variable.
如果const保存着对象,那么修改对象的值是可行的。
const obj = {
name:'san',
age:22
};
obj.age = 100;
console.log(obj.age);//100
3.关于const的变量提升
var x = 10;
function test(){
console.log(x);
const x = 45;
}
test();//Uncaught ReferenceError: Cannot access 'x' before initialization
const只有[创建]和[初始化],当进入执行上下文,收集变量对象时,只有[创建]这个阶段被提前了。所以提示未初始化不能访问x。
关于function
1.函数提升
function test(){
fn();//fn被执行了
console.log(fn);//fn(){console.log('fn被执行了')}
function fn(){
console.log('fn被执行了');
}
}
test();
函数提升是函数名和函数体都提升了。
2.重复定义函数
重复定义的函数还是使用原来分配的内存。
function test(){
console.log('test1');
}
function test(){
console.log('test2');
}
test();//test2
3.变量提升和函数提升
函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。
console.log(a);//ƒ a(){}
var a = 10;
function a(){}
console.log(a);//10
等同于
function a(){}
var a;
console.log(a);//ƒ a(){}
a = 10;
console.log(a);//10