ES6最为经典或适用的基础教程当属 阮一峰 的es6基础入门。比较深入详细的介绍ES6各特性。笔者这篇文章,是基础平时工作较常用的知识的一个梳理。想快入门可以继续往下阅读。
1. let & const
不管是变量和常用都用var来声明。通常会遇到这样的问题:
- 变量可以重复定义
- 可以支持变量提升
- 不支持块级作用域
- 没有所谓的 常量
重复定义
var a = 1;
var a = 2;
cosole.log(a); // 2, 是可以正常执行的
复制代码
变量提升
console.log(a);
var a = 1;
//-------------------
//上面这段代码浏览器实际解析为:
var a;
console.log(a); //a的值为undefined
a = 1;
复制代码
函数声明的提升
a(); //打印 1
function a(){
console.log(1);
}
复制代码
函数表达式不支持函数声明提升
a(); //TypeError: a is not a function
var a = function(){
console.log(2);
}
复制代码
在全局作用域下定义的变量都是window的属性
var a = 1; //等价于 window.a
复制代码
let关键字
let a = 1;
let a = 2; //SyntaxError: Identifier 'a' has already been declared
复制代码
let a = 1;
console.log(window.a); //undefined, 不会污染全局
复制代码
let不支持变量提升
console.log(a); //ReferenceError: a is not defined
let a = 1;
复制代码
块级作用域
//在var定义变量的时候,为了防止变量污染全局,通常采用闭包的形式
//经典的例子:
for(var i = 0; i<3; i++){
setTimeout(function(){
console.log(i); //打印的结果是3,3,3
})
}
//如果为了每次打印一个数字,闭包的写法:
for(var i = 0; i<3; i++){
(function(i){
setTimeout(function(){
console.log(i); //0,1,2
})
})(i);
}
//改用let定义变量i, es6中 {} 代表一个作用域,可以替代闭包的效果
for(let i =0; i<3; i++){
setTimeout(function(){
console.log(i); //0,1,2
})
}
复制代码
const关键字
//const定义的常量是不能被修改的,这句话对吗?
//1.定义不同常量
const PI = 3.14;
PI = 3; //TypeError: Assignment to constant variable.
//2.定义对象常量
const obj = {a: 1};
obj = {a: 2}; //TypeError: Assignment to constant variable.
复制代码
obj.a = 2;
console.log(a); //{ a: 2 }, const定义的常量不能修改常量的引用地址,但是可以修改常量内部的属性值
复制代码
那 let 定义变量的值能修改吗?
let pi = 3.14;
pi = 3.1415; //这是被允许的
复制代码
2. 解构赋值 deconstruction
简单的理解就是:结构相同,变量赋值
数组解构, 数组声明功能
let [name, age] = ['zfpx', 9];
console.log(name, age); // zfpx, 9
复制代码
也可以只取数组中的某一个值:
let [, age] = ['zfpx', 9];
复制代码
对象的解构
let {name, age} = {name: 'zfpx', age: 9}; //ES6中,对象key 和 value 相同时,可以简写成同一个
//如果解构后想在新的对象中重新命名:
let {name: n, } = {name: 'zfpx', age: 9};
//新声明的对象中可以声明默认值
let {name, age, addr: '中关村'} = {name: 'zfpx', age: 9};
//复杂数据结构的解构赋值
let [, , {hobby: [val, [a]]}] = [, , {hobby: ['睡觉', '吃饭']}]
复制代码
- 举例: 函数调用时,参数解构
function ajax({url, data, method='get'}){
}
ajax({
url: '/test',
data: {...}
})
复制代码
3. 字符串 strings
3.1 模板字符串
es5中,拼接字符串常常采用这样的方式:
var name = '东部华侨城', age = 9;
var str = '很高兴来到(' + name + '),今年(' + age + ')岁了';
//还有字符串中有特殊字符还得转义
var str = '\'很高兴来到\'' + age + ', 今年' + age + '岁了';
//在模板字符串中很简单的解决这些问题:
//反引号
let name = '东部华侨城', age = 9;
let str = `很高兴来到${name}, 今年${age}岁了`
//可以加入任意字符
let str = `高兴'来到'(${name}), 今年(${age})岁`;
//字符串很长时,可以回车换行,不用 + 来拼接,阅读起来更加方便
复制代码
3.2 模拟模板字符串的实现
let name = '东部华侨城';
let addr = '深圳盐田区';
let str = '${name}很漂亮,位于${addr}'
let newStr = str.replace(/\${([^}]+)\}/g, function(){
return eval(arguments[1]);
});
复制代码
3.3 自定义模板规则
fn`${name}很漂亮,位于${addr}`
复制代码
let name = '东部华侨城';
let addr = '深圳盐田区';
function fn(strings){
//strings: [ '', '很漂亮,位于', '' ];
//arguments: { '0': [ '', '很漂亮,位于', '' ], '1': '东部华侨城', '2': '深圳盐田区' }
let args = Array.prototype.slice.call(arguments, 1);
//args: [ '东部华侨城', '深圳盐田区' ]
let str = '';
for(let i = 0; i < args.length; i++){
str += strings[i] + `(${args[i]})`;
}
str += strings[strings.length - 1];
return str;
}
let newStr = fn`${name}很漂亮,位于${addr}` //留意这里
console.log(newStr);
复制代码
3.4 字符串函数
startsWith() 类似于 indexOf()
endsWith();
padStart();
padEnd();
includes();
复制代码
4. 箭头函数
1.箭头函数没有function, 没有arguments 需要自己创造arguments
let fn = (a) => { a }
let arrow = (...arguments) =>{
console.log(arguments); //[1,2,3,4,5]
}
arrow(1,2,3,4,5);
2.箭头函数内部没有this指向
箭头函数与定义时所处的上下文没有关系,与调用时的上下文有关系
箭头函数中: 谁调用,this指向谁
let obj = {
name: '东部华侨城',
fn: () => setTimeout(() => {
console.log(this) ; // 打印的是 Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
}),
fn1(){
console.log(this); // 打印的 {name: "东部华侨城", fn: ƒ, fn1: ƒ}
}
}
obj.fn(); //相当于obj.fn()执行后返回 setTimeout(...), 实际上也就是 window.setTimeout 来调用
obj.fn1();
3.箭头函数不用 return 时可以不写 {}
let fn = (a) => a
4.如果只有一个参数, 可以不写 ()
let = a => a
复制代码
5. 展开运算符 spread
6. 数组 array, Set, Map
7. object
9. promise
未完待续...