1.变量声明(hoisting)
var 变量的作用域是它当前(声明位置)的执行上下文;由于声明总是在任意代码执行之前处理,所以在代码中的任意位置声明总是等效于在代码(函数或者全局)开头声明,这个行为叫做变量提升(变量可以在声明之前使用,值为undefined)
console.log(x); //undefined
var x = '123'
let 变量的作用域是声明位置的块或子块
console.log(x); //ReferenceError
let x = '123'
const 声明一个只读的常量,一旦声明值就不能改变,即声明时必须立刻初始化
const x = '123'
let和const仅在声明的代码块内有效且无变量提升,同一区块中不允许重复声明同一个变量。
ES6规定如果区块中存在let和const命令,这个区块对这些命令声明的变量从一开始就形成了封闭作用域,即凡是在声明之前使用变量就会报错,在语法上叫做暂存死区(temporal dead zone,TDZ)
2.块级作用域
ES6之前只有全局作用域和函数作用域,没有块级作用域
var tmp = new Date()
function f(){
console.log(tmp); //变量提升内部变量tmp覆盖外层变量tmp
if(false) var tmp = 'hi'
}
f() //undefined
var s = 'hello'
for (var i=0;i<s.length;i++){
//do something...
}
console.log(i); //计数的循环变量i泄露为全局变量
let为JS新增了块级作用域
{
{let a = 'abc';}
let a = ‘efg’;
console.log(a); //efg
//外层作用域无法读取内层作用域的变量,内层可以定义外层作用域的同名变量
}
块级作用域可以取代以前的立即执行函数表达式(IIFE)
(function (){ //圆括号将函数声明(匿名函数)转化为函数表达式
//do something...
})() //立刻执行匿名函数
3.箭头函数和rest参数
ES5获取参数数组
function a(arg1, arg2, ...){
var args = [].slice.call(arguments) //[arg1, arg2, ...]
}
ES6引入rest参数(...args),用于获取函数的参数。rest参数是一个真正的数组。
rest参数之后不能再有其他参数,函数length属性不包括rest参数。
(function(a){}).length //1
(function(...a){}).length //0
ES6中允许使用箭头函数定义匿名函数(lambda表达式)
var f = v => v;
等同于
var f = function (v){return v;}
无参数或多个参数时使用圆括号代表参数部分
var f = () => 5;
var sum = (num1, num2) => num1 + num2;
代码块多于一条语句使用大括号和return语句返回
var sum = (num1, num2) => {return num1 + num2;}
{}会被解析成语句,因此返回一个对象时必须在对象(字面量)外加括号
let getItem = id => ({id: id})
结合rest参数
const numbers = (...nums) => nums;
numbers(1, 2, 3, 4 , 5);