块级作⽤域绑定
变量提升机制
在函数作用域或者全局作用域中,通过var声明的变量,无论在哪里声明,都会被当做成在当前作用域或顶部声明,这就是函数提升(Hoisting)
块级作用域
块级声明用于再制定块的作用域之外无法访问的变量。块级作用域存在于:
- 函数内部
- 大括号之间的区域
let声明
let对变量声明,不能变量提升
if (true) {
let age = 20
}
console.log(age) // 报错
注意:
- 禁止重复声明
var a = 0
let a = 1 // 报错
var a = 0
if (true) {
let a = 1 // 不报错
}
- 块级不会提升
console.log(a) // 会报错(临时死区Temporal Dead Zone)
console.log(typeof a) // 会报错
let a = 1
console.log(a) // undefined 变量提升
var a = 1
const声明
对常量的声明,同样也不会变量提升。目前的普遍推荐方式是:默认使用const,只有确实需要改变的变量时才会用let。
注意:
- 有效的常量声明
const a = 1 // 有效
const a // 无效
const a = 0 // 重复声明,报错
- 用const声明对象时,不允许修改绑定,但允许修改值
const person = {
age: 20
}
person.age = 21 // 有效
循环中的块级作⽤域
⻓久以来,var声明让开发者在循环中创建函数变的异常困难,因为变量到了循环之外仍能访问。为了
解决这个问题,开发者在循环中使⽤⽴即调⽤函数表达式。
// 使⽤⾃执⾏函数
var fns = []
for (var i = 0; i < 10; i++) {
fns.push(function(i) {
return function() {
console.log(i);
};
}(i));
}
fns.forEach(function(fn) {
fn(); // 输出0到9
});
// 使⽤let
var fns = [];
for (let i = 0; i < 10; i++) {
fns.push(function() {
console.log(i);
});
}
fns.forEach(function(fn) {
fn(); // 输出0到9
});
全局块作⽤域绑定
let和const与var的另外⼀个区别是他们在全局作⽤域中的⾏为。这意味着var很可能⽆意间覆盖了⼀个
已经存在的全局属性。
var name = 'jinxing'
console.log(window.name) // jinxing
let name = 'jinxing'
console.log(window.name === name) // false
函数
函数形参默认值
// es5
function person(name) {
name = typeof name !== 'undefined' ? name : 'jinxing'
}
// es6
function person(name = 'jinxing') {
...
}
注意:
- 前⾯的参数默认值不能引⽤后⾯的参数值
function add(a, b = 1) {
return a + b
}
console.log(add(1, 1)) // 2
function addition(a = b, b) {
return a + b
}
console.log(addition(undefined, 1)) // 报错
处理⽆命名参数
在函数的命名参数前添加三个点(…)就标识这是⼀个不定参数,是个数组。
function add(...keys) {
console.log(args.length); // 2
console.log(arguments.length); // 2
console.log(args[0], arguments[0]); // 1 1
console.log(args[1], arguments[1]); // 2 2
}
add(1, 2);
注意:
-
…必须是最后一个参数
-
setter中不能使用…
let object = {
set name(...value) {} // 报错
}
扩展运算符
执⾏函数时,传⼊展开后的参数
a(...value, 0)
箭头函数
es6中的新特性,通过 参数 => 函数体 的⽅式调⽤。
特性
-
没有this、super、arguments,new.target绑定。this、super、arguments以及内部函数的
new.target的值由所在的最近的外部⾮箭头函数来决定。
-
不能使⽤new来调⽤。箭头函数没有[[Construct]]⽅法,因此不能被⽤为构造函数,使⽤new调⽤函数会抛出错误。
-
没有原型。没有使⽤new,因此没有prototype属性。
-
不能修改this的绑定。不能通过call(),apply()以及bind()⽅法修改this。
-
没有arguments对象。需要通过命名参数和不定参数这两种形式访问函数的参数。
-
不允许使⽤重复的具名参数。箭头函数不允许拥有重复的具名参数,⽆论是否在严格模式下。
注意:
- 箭头函数没有arguments对象,但可以访问上⼀层函数的arguments对象
function outer() {
return () => arguments[0]
}
var result = outer(1,2,3)
console.log(result()) // 1
- 如果需要返回对象的话,需要使⽤圆括号()将对象包裹起来,为了防⽌对象字⾯量被认为是函数体语句。
扩展对象的功能性
对象字⾯量语法扩展
- 属性初始值的简写
// es5
function demo(name, age) {
return {
name: name,
age: age
}
}
// es6
function demo(name, age) {
return { name, age }
}
- 对象⽅法的简写
// es5
var demo = {
name: 'jinxing',
getName: function() {
console.log(this.name);
}
}
// es6
let demo = {
name: 'jinxing',
getName() {
console.log(this.name);
}
}
- 可计算属性名
// es5
var demo = {
'first name': 'jinxing'
}
console.log(demo['first name']);
// es6
let firstName = 'first name'
let demo = {
[firstName]: 'xiao'
}
console.log(demo[firstName])
es6新增⽅法
Object.is()
Object.assign()
解构
对象的解构
let person = {
name: 'jinxing',
age :18
}
let { name, age } = person
console.log(name) //hello
console.log(age) //18
为不同名的变量赋值
let person = {
name: 'jinxing',
age :18
}
{ name: localName, age: localAge, value = true } = person; // 等号是赋默认值,冒号是为别名赋值
console.log(localName); //hello
console.log(localAge); //18
console.log(value); // true
嵌套的对象解构
let person = {
name: 'jinxing'
school: {
university: {
start: 2018
end: 2020
}
}
}
let { school: { university } } = person;
console.log(university.start); // 2018
console.log(university.end); // 2020
数组的解构
let arr = [1, 2, 3]
let [first, second] = arr;
console.log(first) // 1
console.log(second) // 2
解构赋值与默认值
let arr = [1, 2, 3]
[first, second, third = 100] = arr
[first, second] = [second, first] // 变量值互换
console.log(first) // 2
console.log(second) // 1
console.log(third) // 100
剩余项
let aaa = [1, 2, 3, 4, 5]
let [first, ...subArr] = aaa
console.log(first); // 1
console.log(subArr.length) // 4
console.log(subArr[0]) // 2
// 深拷⻉数组
let bbb = [1, 2, 3, 4, 5]
let [...clonedArr] = bbb
console.log(clonedArr) // [1, 2, 3, 4, 5]
参数解构
function setCookie(name, value, {
secure = false,
path = "/",
domain = "example.com",
expires = new Date(Date.now() + 360000000)
} = {} ) {
//...
}