对于后端程序猿来说,对前端知识的了解大多数停留在会用javascript写个函数,google一下copy一个页面特效代码,对es5、es6了解的不多,甚至都没听说过。今天我就来和大家聊聊es5、es6的知识点
- ES概述
- ES6特性
- 块级作用域
- 变量的解构赋值
- 字符串的方法
- 模板字符串
- 模块化
- 箭头函数
- 延展操作符(Spread operator)
ES概述
ECMAScript(以下简称ES)是JavaScript语言的标准,它是由国际标准化组织(ECMA)制定的, ECMAScript和JavaScript的关系是,前者是后者的规格,后者是前者的一种实现。
- 1999年12月,ECMAScript3版正式发布
- 2000年ECMAScript4流产,具体原因问goodle
- 2009年12月,ECMAScript5版正式发布
- 2015年6月,ECMAScript6版正式发布
ES6特性
ES6对之前的ES5做了大幅度提升,增加了很多新特性。
-
块级作用域 关键字let, 常量const
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
==上面代码中,变量i是var声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。==
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
==上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。==
-
变量的解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
// 以前,为变量赋值,只能直接指定值。
var a = 1;
var b = 2;
var c = 3;
//ES6允许这样写
var [a, b, c] = [1, 2, 3];
//解构不仅可以用于数组,还可以用于对象。
var { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
-
字符串的方法
- includes() 返回布尔值,表 示是否找到了参数字符串
- startsWith() 返回布尔值,表示参数字符串是否在源字符串的头部
- endsWith() 返回布尔值,表示参数字符串是否在源字符串的尾部
//这三个方法都支持第二个参数,表示开始搜索的位置。
'hello world'.includes('world') //true
'hello world'.includes('world',7) //false
'hello world'.startsWith('hell') //true
'hello world'.startsWith('hell',1) //false
'hello world'.endsWith('world') //true
'hello world'.endsWith('world',1) //false
==endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。==
- repeat() 返回一个新字符串,表示将原字符串重复n次。
'x'.repeat(3) // "xxx"
- padStart() 用于头部补全
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
- padEnd() 用于尾部补全
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
-
模板字符串
传统的JavaScript语言,输出模板通常是这样写的。
var product = {name:'',price:120,image:'http:/product.png'};
$('body').append(
'<div><img src="' + product.image + '/></div>' +
'<p>' + product.name + '</p>'+
'<p>' + product.price + '</p>'
);
上面这种写法相当繁琐不方便,ES6引入了模板字符串解决这个问题。
var product = {name:'',price:120,image:'http:/product.png'};
$('body').append(`<div><img src="${product.image}" /></div>
<p>${product.name}</p>
<p>${product.price}</p>
`);
==模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。==
-
模块化
ES5不支持原生的模块化,在ES6中模块作为重要的组成部分被添加进来。模块的功能主要由 export 和 import 组成。每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口,通过import来引用其它模块提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。
- export
//abc.js
//导出变量
export var name = '我是变量';
//导出常量
export const C_NAME = '我是常量';
//导出函数
export function add(x,y){
return x + y;
}
//导出多个变量
var a = 'Hello';
var b = 'World';
export {a,b};
import {a,b} from 'abc.js';
import {add} from 'abc.js';
import {name} from 'abc.js';
==export default 命令==
从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
// export-default.js
export default function () {
console.log('foo');
}
上面代码是一个模块文件export-default.js,它的默认输出是一个函数。
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
// import-default.js
import customName from './export-default';
customName(); // 'foo'
-
箭头函数
这是ES6中最令人激动的特性之一。=>不只是关键字function的简写,它还带来了其它好处。箭头函数与包围它的代码共享同一个this,能帮你很好的解决this的指向问题。有经验的JavaScript开发者都熟悉诸如var self = this;或var that = this这种引用外围this的模式。但借助=>,就不需要这种模式了。
箭头函数的箭头=>之前是一个空括号、单个的参数名、或用括号括起的多个参数名,而箭头之后可以是一个表达式(作为函数的返回值),或者是用花括号括起的函数体(需要自行通过return来返回值,否则返回的是undefined)。
// 箭头函数的例子
// 无参数
()=>1
//一个参数,直接返回表达式
v=>v+1
//多个参数,直接返回表达式
(a,b)=>a+b
//函数体
()=>{
alert("foo");
}
//函数体
e=>{
if (e == 0){
return 0;
}
return 1000/e;
}
==坑点:不论是箭头函数还是bind,每次被执行都返回的是一个新的函数引用,因此如果你还需要函数的引用去做一些别的事情(譬如卸载监听器),那么你必须自己保存这个引用。==
// 错误的写法
class PauseMenu extends React.Component{
componentWillMount(){
AppStateIOS.addEventListener('change', this.onAppPaused.bind(this));
}
componentWillUnmount(){
AppStateIOS.removeEventListener('change', this.onAppPaused.bind(this));
}
onAppPaused(event){
}
}
//正确的写法
class PauseMenu extends React.Component{
componentWillMount(){
AppStateIOS.addEventListener('change', this.onAppPaused);
}
componentWillUnmount(){
AppStateIOS.removeEventListener('change', this.onAppPaused);
}
onAppPaused = (event) => {
//把函数直接作为一个arrow function的属性来定义,初始化的时候就绑定好了this指针
}
}
-
延展操作符(Spread operator)
延展操作符 ==...== 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造对象时, 将对象表达式按key-value的方式展开。
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
//不使用延展操作符
console.log(sum.apply(null, numbers));
//使用延展操作符
console.log(sum(...numbers));// 6
const stuendts = ['Jine','Tom'];
const persons = ['Tony',... stuendts,'Aaron','Anna'];
conslog.log(persions)// ["Tony", "Jine", "Tom", "Aaron", "Anna"]
//在React中的应用
var params = {
name: '123',
title: '456',
type: 'aaa'
}
var { type, ...other } = params;
<CustomComponent type='normal' number={2} {...other} />
//等同于
<CustomComponent type='normal' number={2} name='123' title='456' />