第一章
es6标准入门这本书我读了好几遍,都是比较易懂的语法糖,但是每次读都有新的体会。为了能在新的工作中用到它,从入职跟谁学之前突击看了一遍算起,已经用ES6实战了10个月。借助这次跟大家分享机会,重新整理,把我的心得体会和理解分享给大家,希望对我和对大家都有收获。
草案阶段
Stage 0 - Strawman(展示阶段)
Stage 1 - Proposal(征求意见阶段)
Stage 2 - Draft(草案阶段)
Stage 3 - Candidate(候选人阶段)
Stage 4 - Finished(定案阶段)
一个提案只要能进入 Stage 2,就差不多肯定会包括在以后的正式标准里面。
认识Babel
配置文件.babelrc
{
"presets": ["es2015", "react", "stage-0"],
"plugins": [
"transform-es2015-modules-amd"
],
"env": {
"build": {
"optional": ["optimisation", "minification"]
}
}
}
这个是BOSS系统的一个配置文件
第二章 let 和const 命令
1、什么是状态提升
1)变量的声明被提升到函数顶部
2)初始化操作仍旧留在原处执行
console.log(s);
var s = 2;
console.log(s);
function a() {
if(false) {
var str ;
str='liang';
console.log(str);
} else {
console.log(str);
}
}
a();
请仔细观察输出值,为什么?
ES6中,通常用let和set声明,let表示变量,const表示常量。
1)let和const都是块级作用域
2)不存在状态提升
3)const声明不允许修改绑定,但是允许修改值。
const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
const obj = {name:'liang'};
obj.name='zhang';
2、块级作用域 特点
1)在一个函数内部
2)在一个代码块内部
3)离开作用作用域,立刻销毁
4)不允许重复声明
实例:
let abc = 1;
{
let abc = 3;
console.log('{}'+abc);
}
可以任意嵌套
{{{{{let insane = 'Hello World'}}}}};
{{{{
{let insane = 'Hello World'}
console.log(insane); // 报错
}}}};
不允许重复声明
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
3、es5的块级作用域是怎么样的
(function () {
var tmp = ...;
...
}());
// es6块级作用域写法
{
let tmp = ...;
...
}
4、临时性死区(TDZ Tempporal Dead Zone)
// if (true) {
// // TDZ开始
// tmp = 'abc'; // ReferenceError
// console.log(tmp); // ReferenceError
// let tmp; // TDZ结束
// console.log(tmp); // undefined
// tmp = 123;
// console.log(tmp); // 123
// }
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
怎样避免暂时性死区
1)良好的编码习惯
2)避免重复的命名
5、循环中的块作用域绑定
回顾红宝书for循环中的实例
我们还可以在循环中使用,最出名的一道面试题:循环中定时器闭包的考题
在for循环中使用var声明的循环变量,会跳出循环体污染当前的函数。
for(var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i) //5, 5, 5, 5, 5
}, 0)
}
console.log(i) //5 i跳出循环体污染外部函数
//将var改成let之后
for(let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i) // 0,1,2,3,4
}, 0)
}
console.log(i)//i is not defined i无法污染外部函数
5.1、循环中的let声明
var funcs = [];
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
})
}
funcs.forEach(function(func) {
func();
});
const Obj = {
id:1,
name:'liang'
}
for(let i in Obj){
console.log(i);
}
const iterable = ['mini', 'mani', 'mo'];
for (let value of iterable) {
console.log(value);
}
5.2、循环中的const声明
var funcs = [];
for (const i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
})
}
funcs.forEach(function(func) {
func();
});
// 错误
const Obj = {
id:1,
name:'liang'
}
for(const i in Obj){
console.log(i);
}
const iterable = ['mini', 'mani', 'mo'];
for (const value of iterable) {
console.log(value);
}
为什么for-in 和for-of中用const不报错?
总结
1)for-in for-of中let和const表现一致
2)for循环中的特例
for(let i =0;i<10;i++){
console.log(i);
}
for(let i =0;i<10;i++){
const i = 'abc';
console.log(i);
}
var tmp = 123;
// 暂时死区问题
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
//正常
let i = 2;
if(i){
let i =3;
console.log(i);
}
let tmp = 123;
if (tmp) {
let tmp = 456;
console.log(tmp);
}
6、全局块作用域绑定
//浏览器中演示
var abc = 'liang';
console.log(window.abc);
console.log(window.abc === abc)
let abc = 'liang';
console.log(window.abc);
console.log(window.abc === abc)
7、跨模块常量
两种方式
import moment from 'moment';
const yyyyMMdd = 'yyyy-MM-dd';
const YYYYMMDD = 'YYYY-MM-DD';
const YYYYMMDDHHmmss = 'YYYY-MM-DD HH:mm:ss';
const CHINAYYYYMMDDHHmmss = 'YYYY年MM月DD日 HH:mm:ss';
const YYYYMMDDHHmm = 'YYYY-MM-DD HH:mm';
const HHmmss = 'HH:mm:ss';
const HHmm = 'HH:mm';
const CHINAMMDD = 'MM月DD日';
const dateFormat = {
yyyyMMdd: (date) => {
return moment(date).format(yyyyMMdd);
},
YYYYMMDD: (date) => {
return moment(date).format(YYYYMMDD);
},
YYYYMMDDHHmmss: (date) => {
return moment(date).format(YYYYMMDDHHmmss);
},
CHINAYYYYMMDDHHmmss: (date) => {
return moment(date).format(CHINAYYYYMMDDHHmmss);
},
CHINAMMDD: (date) => {
return moment(date).format(CHINAMMDD);
},
YYYYMMDDHHmm: (date) => {
return moment(date).format(YYYYMMDDHHmm);
},
HHmmss: (date) => {
return moment(date).format(HHmmss);
},
HHmm: (date) => {
return moment(date).format(HHmm);
},
toMoment: (date) => {
return moment(date);
},
timeStampMillisecond: (date) => {
return +moment(date);
},
};
const fenToYuan = function (num) {
if (typeof num !== 'number' || isNaN(num)) {
return null;
} else if (num === 0) {
return 0;
}
return (num / 100).toFixed(2);
};
export { dateFormat, fenToYuan };
export const A = 1;
export const B = 2;
8、案列
const self = this;
const { mobile, followupName, startTime, endTime, type } = self.state.searchParams;
const omobile = mobile || '';
const ofollowupName = encodeURI(followupName || '');
const ostartTime = startTime || '';
const oendTime = endTime || '';
const otype = (type === undefined || type === null) ? '&type=' : self.handleType(type);
最佳实践
在实际开发中,我们选择使用var、let还是const,取决于我们的变量是不是需要更新,通常我们希望变量保证不被恶意修改,而使用大量的const,在react中,props传递的对象是不可更改的,所以使用const声明,声明一个对象的时候,也推荐使用const,当你需要修改声明的变量值时,使用let,var能用的场景都可以使用let替代。