博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ECMAScript 6不完全教程
阅读量:6077 次
发布时间:2019-06-20

本文共 10943 字,大约阅读时间需要 36 分钟。

1. 尝试ES6

这里有三种简单地方式用于ES6编程:

  1. Web浏览器:使用,可以将ES6编译成ES5的平台,并且并不需要安装。

  2. 命令行:使用babel-node,可以执行ES6的Node.js版本(会在内部编译es5)。需要通过npm安装。

  3. 各种js引擎:根据,找出被支持的ES6功能。

对于第一点和第二点,这有更多细节。

1.1 Babel REPL

Babel REPL主要有四个部分:

1、左上角包含es6源代码

2、左下角可以查看es6中的语法错误
3、右上角是es6被编译成es5的源代码
4、右下角是通过console.log()的输出结果

1.2 babel-node

babel-node可以通过npm安装:

$ npm install --global babel

跟node一样,可以命令开启REPL交互:

$ babel-node

一旦开启REPL,就可以去执行ES6代码:

> let arr = [1, 2, 3];> arr.map(x => x * x)[ 1, 4, 9 ]

注意:

Babel官网上有管多关于的工具。

2. 从var到let/const

es6有两种新的方式来声明变量:

1、let用于声明块级作用于变量
2、const用于声明常量,其值不能被改变。

letconst可以用来替代var声明变量,但是不能盲目使用,因为不同的作用域会改变代码的行为。例如:

var x = 3;    function func(randomize) {        if (randomize) {            var x = Math.random(); // (A) scope: whole function            return x;        }        return x; // accesses the x from line A    }    func(false); // undefined

func()会意外地返回undefined。你可以重写这部分代码,就知道为什么返回undefined了:

var x = 3;    function func(randomize) {        var x;        if (randomize) {            x = Math.random();            return x;        }        return x;    }    func(false); // undefined

如果用let代替之前的var,就会得到不同的结果:

let x = 3;    function func(randomize) {        if (randomize) {            let x = Math.random();            return x;        }        return x;    }    func(false); // 3

因此,盲目地用letconst代替var是有风险的,我的建议是:

1、只在新代码中使用letconst
2、丢弃旧代码或仔细认证

更多信息:

3. 从IIFEs到代码块

在es5中,如果要维护本地变量,不得不使用IIFE:

(function () {  // open IIFE        var tmp = ···;        ···    }());  // close IIFE        console.log(tmp); // ReferenceError

而在es6中,则只需要代码块和let声明:

{  // open block        let tmp = ···;        ···    }  // close block        console.log(tmp); // ReferenceError

更多信息:

4. 从字符串拼接到模板常量

在es6中,对于字符串插值和多行字符串,Javscript能得到其字面值。

4.1 字符串插值

在es5中,是将结果放在字符串中进行拼接:

function printCoord(x, y) {        console.log('('+x+', '+y+')');    }

es6中,通过字符串字面模板,可以在字符串中插入变量值:

function printCoord(x, y) {        console.log(`(${x}, ${y})`);    }
4.2 多行字符串

模板字面量也能输出多行字符串。

例如,在es5中,输出多行字符串,得这样:

var HTML5_SKELETON =        '\n' +        '\n' +        '\n' +        '    
\n' + ' \n' + '\n' + '\n' + '\n' + '\n';

如果通过反斜线转义新行,代码看起来会舒服点(但还是要显示的添加新行):

var HTML5_SKELETON = '\        \n\        \n\        \n\            
\n\ \n\ \n\ \n\ \n\ ';

而es6得模板字面量能跨多行:

const HTML5_SKELETON = `                                    
`;

更多信息:

5. 从函数表达式到箭头函数

在es5中,在函数表达式中必须小心使用this。在示例中,我创建了辅助变量_this_,以便于我能再line B处使用:

function UiComponent {        var _this = this; // (A)        var button = document.getElementById('myButton');        button.addEventListener('click', function () {            console.log('CLICK');            _this.handleClick(); // (B)        });    }    UiComponent.prototype.handleClick = function () {        ···    };

在es6中,可以使用箭头函数,它不会影响this

class UiComponent {        constructor() {            let button = document.getElementById('myButton');            button.addEventListener('click', () => {                console.log('CLICK');                this.handleClick(); // (A)            });        }        handleClick() {            ···        }    }

对于只返回结果的短小回调函数,箭头函数是非常便利的。

在es5中,如下的回调是相对冗长的:

var arr = [1, 2, 3];    var squares = arr.map(function (x) { return x * x });

在es6中,箭头函数会更简洁:

let arr = [1, 2, 3];    let squares = arr.map(x => x * x);

在定义参数时,如果只有一个参数,括号是可以省略的。因而,(x) => x x and x => x x 都是允许的。

更多信息:

6. 处理多个返回值

一些函数或方法能通过数组或对象返回多个值。在es5中,总是需要创建中间变量来访问返回值。es6中,可以使用解构。

6.1 通过数组返回多个值

exec()返回类数组对象的捕获组。es5中,当要访问捕获组的值时,需要一个中间变量:

var matchObj =        /^(\d\d\d\d)-(\d\d)-(\d\d)$/        .exec('2999-12-31');    var year = matchObj[1];    var month = matchObj[2];    var day = matchObj[3];

es6中,解构使代码更简单:

let [, year, month, day] =        /^(\d\d\d\d)-(\d\d)-(\d\d)$/        .exec('2999-12-31');

空得逗号表示跳过数组的第一个元素。

6.2 通过对象返回多个值

Object.getOwnPropertyDescriptor()会返回一个属性描述符对象。

es5中,仍需要一个中间变量来访问你感兴趣的对象属性值:

var obj = { foo: 123 };        var propDesc = Object.getOwnPropertyDescriptor(obj, 'foo');    var writable = propDesc.writable;    var configurable = propDesc.configurable;        console.log(writable, configurable); // true true

es6,可以使用解构:

let obj = { foo: 123 };        let {writable, configurable} =        Object.getOwnPropertyDescriptor(obj, 'foo');        console.log(writable, configurable); // true true

{writable, configurable}的值如下:

{ writable: writable, configurable: configurable }

更多信息:

7. 从for到forEach再到for-of

先说es6,一般会这样迭代数组:

var arr = ['a', 'b', 'c'];    for (var i=0; i

也可以使用ArrayforEach

arr.forEach(function (elem) {        console.log(elem);    });

for循环的优点是可以中断,forEach的优点是简洁。

而es6的for-of循环则结合了两者的优点:

let arr = ['a', 'b', 'c'];    for (let elem of arr) {        console.log(elem);    }

for-of循环也能通过数组的entries方法和解构返回数组的索引和对应的值:

for (let [index, elem] of arr.entries()) {        console.log(index+'. '+elem);    }

更多信息:

8. 参数默认值

es5中,指定参数默认值得这样:

function foo(x, y) {        x = x || 0;        y = y || 0;        ···    }

es6有个更简洁的语法:

function foo(x=0, y=0) {        ···    }

es6语法还一个优点:参数默认值只能被undefined触发,而在es5中,则会被任何z为false的值触发。

更多信息:

9. 命名参数

在Javascript中,命名参数的普遍方式是对象字面量:

selectEntries({ start: 0, end: -1 });

其等价实现:

function selectEntries(options) {        var start = options.start || 0;        var end = options.end || -1;        var step = options.step || 1;        ···    }

es6中,解构是语法更简单:

function selectEntries({ start=0, end=-1, step=1 }) {        ···    }
9.1 使参数可选

es5中使参数可选的做法是这样的:

function selectEntries(options) {        options = options || {}; // (A)        var start = options.start || 0;        var end = options.end || -1;        var step = options.step || 1;        ···    }

es6中,可以指定{}为参数的默认值:

function selectEntries({ start=0, end=-1, step=1 } = {}) {        ···    }

更多信息:

10. 从arguments到参数扩展

es5中,若想让方法或函数接受任意个数的参数,就必须使用指定的arguments变量:

function logAllArguments() {        for (var i=0; i < arguments.length; i++) {            console.log(arguments[i]);        }    }

es6中,可以使用...操作达到同样地效果:

function logAllArguments(...args) {        for (let arg of args) {            console.log(arg);        }    }

还有更nice的语法:

function format(pattern, ...args) {        ···    }

而es5中的处理则相对笨拙:

function format() {        var pattern = arguments[0];        var args = arguments.slice(1);        ···    }

更多信息:

11. 从apply到散布操作符(...)

es5中,apply()会将数组转会成参数,es6中使用散布操作符达到同样地目的。

11.1 Math.max()

es5-->apply():

> Math.max.apply(null, [-1, 5, 11, 3])    11

es6-->spread operator:

> Math.max(...[-1, 5, 11, 3])    11
11.2 Array.prototype.push()

es5-->apply():

var arr1 = ['a', 'b'];    var arr2 = ['c', 'd'];        arr1.push.apply(arr1, arr2);        // arr1 is now ['a', 'b', 'c', 'd']

es6-->spread operator:

let arr1 = ['a', 'b'];    let arr2 = ['c', 'd'];        arr1.push(...arr2);        // arr1 is now ['a', 'b', 'c', 'd']

更多信息:

12. 从concat()到(...)

ES5 – concat():

var arr1 = ['a', 'b'];    var arr2 = ['c'];    var arr3 = ['d', 'e'];        console.log(arr1.concat(arr2, arr3));        // [ 'a', 'b', 'c', 'd', 'e' ]

ES6 – spread operator:

let arr1 = ['a', 'b'];    let arr2 = ['c'];    let arr3 = ['d', 'e'];        console.log([...arr1, ...arr2, ...arr3]);        // [ 'a', 'b', 'c', 'd', 'e' ]

更多信息:

13. 从构造器到类

对于构造器语法,es6的类则更简便。

13.1 基本类

es5中实现一个基本类如下:

function Person(name) {        this.name = name;    }    Person.prototype.describe = function () {        return 'Person called '+this.name;    };

es6中,类提供了更简洁的语法:

class Person {        constructor(name) {            this.name = name;        }        describe() {            return 'Person called '+this.name;        }    }

13.2 派生类

es5实现了类的派生,下面是实现派生类的一种规范方法:

function Employee(name, title) {        Person.call(this, name); // super(name)        this.title = title;    }    Employee.prototype = Object.create(Person.prototype);    Employee.prototype.constructor = Employee;    Employee.prototype.describe = function () {        return Person.prototype.describe.call(this) // super.describe()               + ' (' + this.title + ')';    };

es6内置了类派生语法,要借助extends关键字:

class Employee extends Person {        constructor(name, title) {            super(name);            this.title = title;        }        describe() {            return super.describe() + ' (' + this.title + ')';        }    }

更多信息:

14. 从自定义error到Error派生

跟上面有点类似。es5中自定义error:

function MyError() {        // Use Error as a function        var superInstance = Error.apply(null, arguments);        copyOwnPropertiesFrom(this, superInstance);    }    MyError.prototype = Object.create(Error.prototype);    MyError.prototype.constructor = MyError;

es6通过派生实现:

class MyError extends Error {    }

更多信心:

15. 从对象字面量的函数表达式和方法定义

语法上的差别。es5实现:

var obj = {        foo: function () {            ···        },        bar: function () {            this.foo();        }, // trailing comma is legal in ES5    }

es6:

let obj = {        foo() {            ···        },        bar() {            this.foo();        },    }

更多信息:

16. 从对象到图

es5中利用对象来实现图的数据结构,需要将对象的prototype指向null,并保证__proto__上没有对应的键。

var dict = Object.create(null);    function countWords(word) {        var escapedWord = escapeKey(word);        if (escapedWord in dict) {            dict[escapedWord]++;        } else {            dict[escapedWord] = 1;        }    }    function escapeKey(key) {        if (key.indexOf('__proto__') === 0) {            return key+'%';        } else {            return key;        }    }

es6则内置了Map数据结构;

let map = new Map();    function countWords(word) {        let count = map.get(word) || 0;        map.set(word, count + 1);    }

更多信息:

17. 从CommonJS模块到es6 模块

es5中,模块系统是基于AMD或CommocJS语法。es6内置了模块语法,但并没有得到Javascript引擎良好支持。

17.1 多个导出

在CommonJS中,可以这样实现:

//------ lib.js ------    var sqrt = Math.sqrt;    function square(x) {        return x * x;    }    function diag(x, y) {        return sqrt(square(x) + square(y));    }    module.exports = {        sqrt: sqrt,        square: square,        diag: diag,    };        //------ main1.js ------    var square = require('lib').square;    var diag = require('lib').diag;        console.log(square(11)); // 121    console.log(diag(4, 3)); // 5

es6的语法是酱紫的:

//------ lib.js ------    export const sqrt = Math.sqrt;    export function square(x) {        return x * x;    }    export function diag(x, y) {        return sqrt(square(x) + square(y));    }        //------ main1.js ------    import { square, diag } from 'lib';    console.log(square(11)); // 121    console.log(diag(4, 3)); // 5

或者作为一个对象导入:

//------ main2.js ------    import * as lib from 'lib'; // (A)    console.log(lib.square(11)); // 121    console.log(lib.diag(4, 3)); // 5
17.2 单个导出

Node.js继承了CommonJS的语法,能从模块导出单个值:

//------ myFunc.js ------    module.exports = function () { ··· };        //------ main1.js ------    var myFunc = require('myFunc');    myFunc();

es6通过export default实现:

//------ myFunc.js ------    export default function () { ··· } // no semicolon!        //------ main1.js ------    import myFunc from 'myFunc';    myFunc();

更多信息:


相关文章:

译文出处:

转载地址:http://hcagx.baihongyu.com/

你可能感兴趣的文章
ASP.NET MVC 4 让数据库自动迁移
查看>>
GC算法 垃圾收集器
查看>>
jquery Tabs选项卡切换
查看>>
战略游戏题解
查看>>
Hibernate全套增删改查+分页
查看>>
zabbix server is not running the information displayed may not be current
查看>>
宇宙时光推论
查看>>
如何使用命令行cmd执行java程序
查看>>
20150928js01
查看>>
C#获取磁盘驱动器图标、文件夹图标,文件默认图标
查看>>
OpenCV-Python-边缘检测
查看>>
jQuery 基础之1
查看>>
.NET微信公众号开发-5.0微信支付
查看>>
C# 编写Windows服务、部署、启动以及卸载
查看>>
Oracle的select检索数据
查看>>
企业的组织机构代码javascript脚本校验
查看>>
Python简单爬虫入门二
查看>>
不关闭seLinux解决vsftpd服务本地用户不能登录问题(500 OOPS: cannot change directory:/home/***)...
查看>>
【第一阶段】第二周作业
查看>>
将多个Excel文件合并成一个excel文件
查看>>