react新手必须懂得es6的基础知识
笔者这两天在整理react知识点的时候,顺便对es6的基础知识也进行了一些整理,其实es6出来已经很久了,也不算是一个新的技术了,现在也已经很普及了,所以是时候将它掌握起来了。
一,es6是什么以及为什么要学习它
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
标准的制定者有计划,以后每年发布一次标准,使用年份作为标准的版本。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。也就是说,ES6就是ES2015,下一年应该会发布小幅修订的ES2016。
虽然现在的浏览器还不能支持es6,但是我们能通过babel语法转化器,将es6转化为能被大多数浏览器能够支持的es5。
流行的库基本都基于es6构建,React默认使用es6新语法开发,现在React16.0中。
es6出来已经很久了,笔认为它已经算不上是一个新技术,而且现在已经很普及,将来必定也是一个趋势,而且现在前端这个领域的技术更新迭代特别的快,因此掌握es6显得尤为重要。
二,环境准备,使用react官方推荐的脚手架create-react-app
-
安装nodejs
-
npm install -g create-react-app 安装脚手架
npm install -g create-react-app
- create-react-app es6-demo 创建react项目
cd Desktop // 进入桌面
create-react-app es6-demo // 用脚手架生成es6-demo
三,es6里都有些什么
-
块级作用域,字符串,函数
-
对象扩展,解构
-
类,模块化
1,作用域:let与const
-
定义变量使用let代替var,块级作用域
-
Const定义不可修改的变量
// let:块级作用域
{
var a1 = 'darrell1';
let a2 = 'darrell2'
}
console.log(a1); // darrell1
console.log(a2); // 'a2' is not defined
// const:基本类型
const a3 = 'darrell3'
a3 = 'darrell4'
console.log(a3); // "a3" is read-only
const a = []; // 如果是引用类型的话,往里面添加值是没问题的,但是改变指向后则会报错
a.push('apple');
a.push('egg');
console.log(a); // ["apple", "egg"]
2,字符串:模板字符串
-
使用反引号,直接写变量
-
多行字符串
-
告别+拼接字符串
let name='imooc'
// es5
console.log('hello '+name+'! \n you are funny!')
// es6 after
console.log(`hello ${name}!
you are funny!`) // 换行不需要加\n,直接换行就行
3,函数扩展:ES6中函数的用法
-
参数有默认值
-
箭头函数
-
展开运算符
// 带默认参数的箭头函数
let hello = (name='world')=>{
console.log(`hello ${name}`)
}
// 直接返回值的箭头函数
let cal = num=>num*2
// 多个参数
let cal1 = (num1, num2)=>num1*num2
hello() // hello world
hello('darrell') // hello darrell
console.log(cal(5)) // 10
console.log(cal1(5, 6)) // 30
let arr = [6, 7]
console.log(cal1(...arr)) // ...解构,输出 42
4,对象扩展:Object扩展
-
Object.keys、values、entries
-
对象方法简写,计算属性
-
展开运算符(不是ES6标准,但是babel也支持)
const name = 'imooc'
// es5
const obj = {
name: name,
site:'imooc.com',
sayHello: function(){
console.log('hello world!')
}
}
console.log(obj)
obj.sayHello()
//es6:
//在对象里面添加跟变量名一样的属性址,并且属性的值就是变量的属性址。就可以直接简写成下面这样,函数也可以简写
const obj = {
name,
site:'imooc.com',
sayHello(){
console.log('hello world!')
}
}
console.log(obj)
obj.sayHello()
5,解构赋值,函数也可以多返回值
-
数组结构
-
对象解构
const [name, age] = ['imooc', '20']
const {title,job} = {title:'React开发App', job:'IT'}
console.log(name,age) // imooc,20
console.log(title,job) // React开发App, IT
6,类:提供class的语法糖
-
是prototype的语法糖
-
Extends继承
-
Constructor构造函数
class MyApp{
constructor(age) {
this.name='darrell'
this.age = age
} //用这个类实例化一个对象是,会最先执行这个构造器
sayHello(){
console.log(`hello ${this.name}, I am ${this.age} years old`) //模版字符串
}
}
let app = new MyApp(18)
app.sayHello() // 输出的为:hello darrell, I am 18 years old
7,新的数据结构:ES6中新出现的数据结构
-
Set,元素不可重合
-
Map
-
Symbol
// Set:不能有重复的内容
let desserts = new Set(['tomao','peats','egg']);
desserts.add('toma');
console.log(desserts); // ['tomao','peats','egg','toma']
console.log(desserts.size); 4
console.log(desserts.has('tomao')); // true
desserts.delete('toma');
console.log(desserts) // ['tomao','peats','egg']
desserts.clear(); // []
这几个是es6中新出现的数据结构,我上面就拿set举了一个简单的例子。具体的大家可以去参考考阮一峰老师的ECMAScript 6 入门中关于这几个概念的说明哦。
8,模块化:ES6中自带了模块化机制,告别seajs和require.js
-
Import,import{}
-
Emport,Export default
-
Node现在还不支持,还需要require来加载文件
// module1.js
let fruit = 'apple';
let dessert = 'cake';
let dinner = (fruit,dessert) => {
console.log(`今天的晚餐是${fruit}和${dessert}`);
}
export {fruit,dessert};
export default dinner; // 导出默认的函数
//module2.js
import dinner from './module1.js'; //这个是拿到module1.js默认导出的dinner函数
dinner('apple','egg'); // 今天的晚餐是apple和egg
import * as chef from './module1.js'; // 将module1种所有的export都导出重命名为chef
chef.default('apple','egg');// 今天的晚餐是apple和egg,默认导出的是放在chef的defalut里
chef.default(chef.fruit,chef.dessert); // 今天的晚餐是apple和cake
9,还有一些特性,虽然不在ES6的范围,其他的特性,但是也被babel支持,普遍被大家接受和使用(需要安装插件)。不过这些对于初学者来说,这些暂时还不需要全部掌握。
- Async await
处理异步的方法,非常的简单优雅,具体大家可以参考阮一峰老师的这篇文章,async 函数的含义和用法,
- Promise
new Promise((resolve) => {
setTimeout(function(){
resolve()
}, 3000);
}).then(() => {
console.log('promise 成功');
});
上面是一个简单的例子,我new了一个promise对象,让他在三秒之后可以输出promise 成功,具体的操作大家可以查看,具体的Promise大家可以参考阮一峰老师的ECMAScript 6 入门这本书中对于Promise的讲解,讲的很好。
其实promise更多的是用来获取数据,比如我们在react项目中,会通过fetch发送异步请求,其实fetch返回的就是一个promise对象,所以我们一直.then()
- 迭代器(Iterators)和生成器(Generators)
// 自己实现的一个简单版的迭代器
function chef(foods) {
let i = 0;
return {
next(){
let done = (i >= foods.length);
let value = !done ? foods[i++] : undefined;
return {
value: value,
done:done
}
}
}
}
let anghao = chef(['tomato','egg']);
console.log(anghao.next()); // {value: "tomato", done: false}
console.log(anghao.next()); // {value: "egg", done: false}
console.log(anghao.next()); // {value: undefined, done: true}
//es6 的 Generators
function* chef(foods) {
for(var i = 0 ;i< foods.length;i++) {
yield foods[i]
}
}
//第二种
let wanghao = chef(['tomato','egg']);
console.log(wanghao.next()); // {value: "tomato", done: false}
console.log(wanghao.next()); // {value: "egg", done: false}
console.log(wanghao.next()); // {value: undefined, done: true}
以上是简单的迭代器与生成器的例子,笔者最近在学习阿里的dva
的redux
框架,其中他处理异步数据流的时候使用了redux-saga
,里面有用到生成器。不过对于初学者来说,这些暂时还不需要掌握。
四,结语
个人感觉学习的最好的方法就是去实践,先把一些es6的基础的运用到你日常的工作当中去,将一些原来的es5的方法改写为es6的方法。能帮助我们快速的理解es6的语法。
如在面试过程中我们最常碰到了一道面试题
var funcs = []
for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i) })
}
funcs.forEach(function(func) {
func()
})
这个面试题已经是考作用域的一道经典题目了,答案是输出10个10。
在es5中我们该怎么做,肯定是利用闭包来解决问题,下图是一个立即执行函数。
// ES5告诉我们可以利用闭包解决这个问题
var funcs = []
for (var i = 0; i < 10; i++) {
func.push((function(value) {
return function() {
console.log(value)
}
}(i)))
}
这样我们便能得到0-9,依次输出。
但是当我们有了let
之后,我们可以这样写
// es6
for (let i = 0; i < 10; i++) {
func.push(function() {
console.log(i)
})
}
我们也能得到相同的结果,但是相比于es5的代码,是不是更加简洁呢。
但是这里我想讲的是,虽然es6更加简洁了,但是懂闭包这个概念,可以帮我们更好的理解js的作用域,上下文的关系。
除了上面这个概念,还比如说函数中的this的指向问题,箭头函数的this是指向函数本身的,而es5中的函数则不一定,有些是指向window的。
es6还有很多值得我们去玩的知识点,希望我的这边文章能给大家带来一点点启发。