es6学习手记

本来是要学习现在流行的前端框架的,结果发现好多都在使用es6,所以还是先学习一下es6吧。顺便记录一下自己感觉有用的新特性。

本文的栗子可以在babel官网上运行

let、const以及块状作用域

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)
  • spread:用作传参,可以将数组转换为以逗号隔开的参数。
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。

Object.assign

熟悉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);

set 和 Map

学过Java的同学肯定对着两种数据结构不陌生。

Set:包含的值均是唯一的,没有相同的值。

var s=new Set([1,1,2,3]);
s.add(3);
s.add(4);
console.log(s)//1,2,3,4

常用方法:

  • add(value):添加某个值,返回Set结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。

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

常用方法:

  • set(key,value):添加一个新的成员,如果key已存在,则会用新值替换旧值,返回Map本身。
  • get(key):获取key对应的value,不存在则返回undefined。
  • has(key):判断Map中是否有此key,返回布尔值。
  • delete(key):删除key对应的成员,返回布尔值。

公用方法和属性

  • size:返回成员数量。
  • clear():清除所有成员,没有返回值。
  • keys():返回一个键名的遍历器
  • values():返回一个键值的遍历器
  • entries():返回一个键值对的遍历器
  • forEach():使用回调函数遍历每个成员

类(class)

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 继承自父类

module(模块化)

前端模块化的思想由来已久,es6之前主要有AMD(require.js)/CMD和CommonJS(node.js)来规范js的模块化方案。下面就来介绍一下es6的模块化方案:
在es6中,export用于输出模块,import用于加载模块

  • export
//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}
  • import

使用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 default

输出一个默认值,导入时无需知道输出时的变量名,可以自定义名称,且无需用{}包裹。每个模块只能有一个默认值

//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'
}

你可能感兴趣的:(javascript)