JS的变量提升&ES6基础
- 变量
- var关键字
- var声明作用域
- 实例一
- 实例二
- 多个变量
- 变量提升
- let关键字
- 暂时性死区
- 全局声明
- for循环中使用let
- const关键字
变量
ECMAScript变量时松散类型的,意思是变量可以用于保存任何类型的数据。
声明变量:var 、const、let
var
可以随意使用,而const
和let
只能在ES6及更晚的版本中使用。
var关键字
作用:定义变量(注意:
var
是一个关键字)
var name;
var name='kin';
name = 100;
var声明作用域
实例一
var
操作符定义的变量会成为包含它的函数的局部变量。
function test(){var name = "kin";//局部变量
}
test();
console.log(name);//报错
name变量是在函数内部使用var定义的
函数叫test(),调用它会创建这个变量并给它赋值,调用之后变量随即被销毁。
实例二
在函数内定义变量时省略var操作符,可以创建一个全局变量:
function test(){name = "kin";//全局变量
}
test();
console.log(name);//kin
注意:
虽然可以通过该省略var操作符定义全局变量,但不推荐这么做。在局部作用域中定义的全局变量很难维护,也会造成困惑。这是因为不能一下子断定省略var是不是有意而为之。在严格模式下,如果像这样给未声明的变量赋值,则会导致抛出ReferenceError。
多个变量
var name = "kin";age = 12;
变量提升
function foo(){console.log(age);var age = 26;
}
foo(); // undefined
声明的变量会自动提升到函数作用域顶部
成等价于如下代码
function foo(){var age;console.log(age);age = 26;
}
foo();//undefined
提升------把所有变量声明都拉到函数作用域的顶部
function foo(){var age = 16;var age = 26;var age = 36;console.log(age);
}
foo();//36
反复多次使用var声明同一个变量
let关键字
let
声明的范围是块作用域,var
声明的范围是函数作用域。
if(true){var name = "kin";console.log(name);//kin
}
console.log(name);//kin
对比:
if(true){let age = 26;console.log(age);//26
}
console.log(age);//ReferenceError:age 没有定义
age变量不能在if块外部被引用,是因为他的作用域仅限于该块内容。
块作用域是函数作用域的子集,因此适用于var
的作用域限制同样也适用于let
。
注意:
let
也不允许同一个块作用域对一个变量重复声明。
var name;
var name;let age;
let age;//SyntaxError;标识符age已经声明过了
由于同一个块中没有重复声明,嵌套使用相同的标识符不会报错。
var name = 'kin';
console.log(name);//kin
if(true){var name = '前端';console.log(name);//前端
}let age = 30
console.log(age);//30if(true){let age = 26;console.log(age);//26
}
暂时性死区
let
与var
重要的区别:
let声明的变量不会再作用域中被提升
var声明:
console.log(name)//undefined
var name = "kin"
let声明:
console.log(age)
let age = 18 //ReferenceError:age 没有定义
在let
声明之前的执行瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出ReferenceError。
全局声明
使用let
在全局作用域中声明的变量不会成为window对象的属性。
var name = 'kin';
console.log(window.name);//kin
let age = 26;
console.log(window.age);//undefined
for循环中使用let
使用var
在for循环中定义的迭代变量会渗透到循环体外
for (var i=0;i<5;i++){
}
console.log(i);//5
使用let
在循环中定义的迭代变量仅限于循环块内部
for (let i=0;i<5;i++){
}
console.log(i);//ReferenceError: i is not defined
示例:
for (var i=0;i<5;i++){setTimeout(()=>console.log(i),0)
}
//你认为输出的结果是:0、1、2、3、4
//实际输出:5、5、5、5、5
因为在循环退出的时候,迭代变量报错的事导致循环退出的值:5,在之后执行超时逻辑,所有的i都是同一个变量。
使用let可以解决这个问题
for (let i=0;i<5;i++){setTimeout(()=>console.log(i),0)
}
//0 1 2 3 4
const关键字
const
的行为与let
基本相同。
区别:
- 用
const
声明变量时必须同时初始化变量- 修改
const
声明的变量会导致运行时错误
const age = 18;
age = 20 // TypeError : 给常量赋值
//const 也不允许重复声明
const name = 'kin';
const name = 'nnn';//SyntaxError
const
声明的作用域也是块
const name = 'kin';
if(true){const name = 'nnn';
}
console.log(name);//kin
ok!目前就这些啦,大家有问题欢迎评论区讨论呀!