ES6 基础语法

@eyasliu 2016-07-19 10:16:53发表于 eyasliu/blog 前端

参考文献: http://es6.ruanyifeng.com/

babel

ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。目前浏览器已实现大部分的ES6特性,但是为了兼容性我们需要使用工具babel编译为es5代码。才能让应用正常运行

在浏览器可以使用 chrome 插件 Scratch Js 尝试编写es6,并查看编译后的代码

或者到 babel 在线编译尝试 https://babeljs.io/repl/

let && const

var 声明的变量在整个当前作用域有效,let 和 const声明的变量在代码块有效(块级作用域),cont 声明的变量为常量,不能重新赋值

for(var i = 0; i < 10; i++){}
console.log(i) // 10

for(let i = 0; i < 10; i++){}
console.log(i) // error: i is not defined

解构赋值

按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构

let [a, b, c] = [1, 2, 3]; // a,b,c

let { bar, foo } = { foo: "aaa", bar: "bbb" }; // foo, bar
let { bar: x, foo: y } = { foo: "aaa", bar: "bbb" }; // x, y

对象扩展

定义对象

// 直接写入变量和函数,作为对象的属性和方法
var foo = 'bar';
var baz = {foo};
baz // {foo: "bar"}

// 对象中的函数
var obj = {
  foo(){
    reutrn 'hello'
  }
}

属性名表达式

var key = 'foo';
var obj = {
  [key]: true,
  ['b' + 'ar']: 123
}
obj // {foo: true, bar: 123}

扩展运算符

ES7有一个提案,将Rest解构赋值/扩展运算符(...)引入对象。Babel转码器已经支持这项功能。可以理解为属性展开

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }

let a = {...z} // 克隆对象
a // { a: 3, b: 4 }

let arr = [1,2,3,4,5]
let arr2 = [6,7,8]
let oarr1 = [...arr] // 数组克隆
let oarr2 = [...arr, ...arr2] // 合并数组
oarr1 // [1,2,3,4,5]
oarr2 // [1,2,3,4,5]

[...'hello'] // ['h', 'e', 'l', 'l', 'o']

// function
function foo(...args){
  args // [...arguments]
}
foo(1,2,3) // args = [1,2,3]

函数扩展

函数参数默认值

// 基本用法
function foo(x = 10, y = true, z = {bar: 'str'}){
  return [x, y, z];
}
foo() // [10, true, {bar: 'str'}]

// 结合解构赋值
function foo({x = 10} = {}, y){
  return [x, y];
}
foo() // [10, undefined]
foo({x: 100}, false) // [100, false]

函数length属性

返回没有设置默认值的参数个数

(function (a, b, c = 5) {}).length // 2

箭头函数

ES6允许使用“箭头”(=>)定义函数。

var f = x => x; // 相当于 var f = function(x){return x;}
var b = (x, y) => ({x, y})

注意事项

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,并且this不可改变
  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误
  • 不可以使用arguments对象,该对象在函数体内不存在
  • 不可以使用yield命令,因此箭头函数不能用作Generator函数

函数绑定

函数绑定运算符是并排的两个双冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。

function bar(){
  //
}
var foo = {}
foo::bar // 等同于 bar.bind(foo)

Class

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

//定义类
class Point {
  constructor() {}
  toString(){}
  render(){}
}
// 等价于
function Point(){}
Point.prototype.toSring = function(){}
Point.prototype.render = function(){}

// 类表达式
const Point = class Temp{} // 类的名字为 Point,Temp只会在类的内部使用,Temp可省略

  • constructor 是类的默认方法,用 new 调用时执行的方法
  • 只能使用 new 实例化类
  • 有name属性, Point.name -> 'Point'
  • 不存在变量提升

Class 继承

继承使用 extends 关键字

class ColorPoint extends Point{
  constructor(){
    super() // 调用父类的构造函数,如果有constructor,必须调用,如果没有constructor,后台自动调用
  }
}
  • 只要是有prototype属性的函数,就能被继承
  • 如果继承 null,相当于继承 Function
  • super 代表父类构造函数,也可作为对象调用,可访问父类实例的方法和属性

取值与存值

class Point {
  constructor(){}
  get prop(){}
  set prop(){}
}
let p = new Point
p.prop = 123 // 执行 set prop
p.prop // 执行 get prop

静态属性和方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”

class Foo {
  static classMethod() {
    return 'hello';
  }
  static defaultProps = {}
}

Foo.classMethod() // 'hello'

var foo = new Foo();
foo.classMethod()
// TypeError: undefined is not a function

Module

javascript 模块体系,模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能

export 导出

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。

// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
export function getFullName(){}
export default {firstName, lastName, year} // 默认模块
export * from 'lodash'; // 模块继承,导出lodash模块的所有方法

import 导入

使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)。

// main.js

import {firstName, lastName} from './profile';
import {firstName as fn, lastName as ln} from './profile'; // 重命名
import Profile from './profile';
import Profile as p from './profile';
  • import 有变量提升