本来是要学习现在流行的前端框架的,结果发现好多都在使用es6,所以还是先学习一下es6吧。顺便记录一下自己感觉有用的新特性。
本文的栗子可以在babel官网上运行
const用来定义常量,let也是用来定义变量的,但是用let定义的变量会被限定在当前作用域。
es5没有块状作用域,写代码时经常会造成困扰,本次es6终于添加了。
let m=6;
const n=8;
{
let m=9;
const n=0;
console.log(m)
console.log(n)
}
console.log(m)
console.log(n)
//n=9;//报错
es5可以用单引号或双引号来表示字符串,es6添加了一种用反引号(` `)框起来的,称为模板字符串。
最大的特点是两个反引号之间的内容可以换行,并且支持用${}
来引入javascript表达式。
var m='i am';
var n=
`${m}
template
string
`
console.log(n)
es5写法
function log(x, y) {
var y = y || 'World';//此处还可以重新用var定义y
}
es6写法,支持在参数列表直接赋值,此值即为默认值。
function log(x, y = 'World') {
//let y=6;报错。与参数同名变量再次定义会报错。
console.log(x, y);
}
有两种用法
- rest:用在方法参数列表,有点类似Java的可变参数(void test(String... args)
),规则也差不多
1. 只能有一个rest参数
2. rest参数只能是最后一个
function test(a,...b){
console.log(a)
b.forEach(function(item){
console.log(item)
})
}
test('f','1',2,3,4)
function test(a,b,c){
console.log(a);
console.log(b);
console.log(c);
}
var arr=[1,2]
test(...arr);//1 2 undefined
//复制对象
let m = { a: 1, b: 2 };
let n = { ...m };
箭头函数可概括为:参数列表 => 方法体,如:
var f=(m)=>{console.log(m)}
//等同于
var f = function(m) {
console.log(m);
};
当参数列表或方法体很简洁时可以省略括号:
var m=v=>v;
var n=()=>1;
需要注意的是:箭头函数没有属于自己的this,而是使用外层的this,所以也无法用作构造函数。
什么意思呢?看以下代码:
function out(){
this.num=0;
this.f=()=>{console.log(this.num)}
this.m=function(){
console.log(this.num);
}
}
//翻译为es5后
"use strict";
function out() {
var _this = this;
this.num = 0;
this.f = function () {
console.log(_this.num);
};
this.m = function () {
console.log(this.num);
};
}
可以看到翻译后的箭头函数使用的是外部的this,而普通函数则使用的还是本身的this,结合js‘谁调用函数,this便指向谁’的特性,可以很好的理解二者的不同。
如果我们要定义一个对象,来看es5和es6的写法
var namePro='name';
var age=18;
var es5Obj={
name:'peter',
age:age,
doSth:function(){
console.log(this.name)
}
}
//es6座位
var es6Obj={
[namePro]:'peter',//表达式
age,
doSth(){
console.log(this[namePro])
}
}
es5Obj.doSth();
es6Obj.doSth();
可以看到如果属性名和值用到同一个定义的话可以省略为单个。方法定义可以省略:function
。而最大的特点就是属性名支持表达式[]
了。在中括号中可以写入js表达式,表达式的计算结果即为属性名。如上面的自定义变量namePro。
熟悉jQuery的应该都知道知道用$.extend()
来复制对象,es6提供了类似的方法Object.assign()
,用法也和jQuery差不多。
var obj={
name:'peter',
sayHi(){
console.log('Hi')
}
}
var o1=Object.assign({},obj);
o1.age=18;
var o2=Object.assign({},obj);
o2.age=19;
console.log(obj);
console.log(o1);
console.log(o2);
学过Java的同学肯定对着两种数据结构不陌生。
Set:包含的值均是唯一的,没有相同的值。
var s=new Set([1,1,2,3]);
s.add(3);
s.add(4);
console.log(s)//1,2,3,4
常用方法:
Map:键值对组成的对象。
var a='a';
var m=new Map([
[a,1],
['b','2']
])
m.set('c',3);
console.log(m.get(a)) //1
console.log(m.get('c')) //3
常用方法:
公用方法和属性
es6引入了类、静态这些概念,不禁感慨是否要迎来编程语言大一统!
class Animal{
constructor(x){
this.legs=x;
this.eyes=2;
}
static sayHi(){//静态方法
console.log('hi')
}
shout(msg){
console.log(msg)
}
}
var dog=new Animal(4);
dog.shout('汪');//汪
console.log(dog.legs)//4
var snake=new Animal(0)
snake.shout('嘶')//嘶
console.log(snake.legs)//0
Animal.sayHi()
//dog.sayHi(); not a function
class Dog extends Animal{
constructor(x,y){
super(x)//子类必须调用super,super代表父类的构造函数
this.color=y;
}
showColor(){
console.log(this.color)
}
}
var dog2=new Dog(4,'white')
dog2.showColor()//白色
console.log(dog.legs)//4 继承自父类
前端模块化的思想由来已久,es6之前主要有AMD(require.js)/CMD和CommonJS(node.js)来规范js的模块化方案。下面就来介绍一下es6的模块化方案:
在es6中,export用于输出模块,import用于加载模块
//demo1
export const hello = "hello";
//等价于
const hello = "hello";
export {hello}
输出多个模块可以分开定义,一起输出
//demo2
const hello = "hello";
const fnc=function(){
console.log('peter')
}
export {hello as h,fnc}//hello as h表示将hello输出为h,即定义别名,加载模块时用h来加载
//也可以输出对象或类
let hello={
sayHi:'hi',
fnc(){
console.log('peter')
}
}
export {hello as h}
使用export的文件可以用import来加载,格式为 import xxx from 'js文件'
//对应上面的demo2
import {h,fnc} from './hello_es6'//也可以写为
let root=document.getElementById('root');
root.innerHTML=h;
fnc();
//对象
import {h as hello} from './hello_es6'//import也可使用as定义别名
let root=document.getElementById('root');
root.innerHTML=hello.sayHi;
hello.fnc();
还有一种加载模式,分散导出,整体加载。
//对应demo2例一
import * as h from './hello_es6'//可以理解为将hello_es6导出的东西放到h中去
let root=document.getElementById('root');
root.innerHTML=h.hello;
h.fnc();
输出一个默认值,导入时无需知道输出时的变量名,可以自定义名称,且无需用{}
包裹。每个模块只能有一个默认值
//export
const hello = "hello";
export default hello;
//import
import h from './hello_es6'
let root=document.getElementById('root');
root.innerHTML=h;
最后,无论是export还是import都只能写在文件的顶层模块,而不能写在其他代码块中,否则报错。
//错误示例
{export {hello};}
if(true){
import h from './hello_es6'
}