原文阅读请点击此处

一、let和const

{
    // let声明的变量只在let命令所在的代码块内有效
    let a = 1;
    var b = 2;
}

console.log(a);     // 报错: ReferenceError: a is not defined
console.log(b);
// for循环的技术器就很适合let命令
for (let i = 0; i < 3; i++) {
    console.log(i);
}

console.log(i); // ReferenceError: i is not defined
// 这里的i是var声明的,在全局范围内有效,素偶一每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i值
for (var i = 0; i < 10; i++) {
    a[i] = function() {
        console.log(i);
    }
}

a[6](); // 10

var b = [];

// 使用let声明的变量尽在块级作用域内有效,所以每一次循环的j其实都是一个新的变量,于是最后输出6
for (let j = 0; j < 10; j++) {
    a[j] = function() {
        console.log(j);
    }
}

b[6]();
// let不像var那样会发生"变量"提升的现象
// 但是经过babel转换器转换之后,还是存在变量提升的现象
// ES6明确规定,如果区块中存在let和const命令,则这个区块中对这些命令声明的变量从一开始就形成封闭作用域.只要在声明这些变量之前就使用这些变量,就会报错
{
    console.log(foo);   // ReferenceError
    let foo = 2;
}

// 块级作用域
{
    // 块级作用域的出现使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了
    // IIFE写法
    (function() {
        var tmp = 'a';
        // ...
    })();

    // 块级作用域写法
    {
        let tmp = 'a';
        // ...
    }

    // 因此,我们可以使用块级作用域来划分业务模块,以及避免全局变量

}

{
    let a = 'secret';

    function f() {
        return a;
    }
}

f();    // 报错
// const声明的常量不得改变值
// const一旦声明常量,就必须立即初始化,不能留到以后赋值
// const的作用域与let命令相同:只在声明所在的块级作用域内有效
// const命令声明的变量也不提升,只能声明后使用
const foo = 'AAA';
foo = 'BBB';    // 编译不通过
{
    // 跨模块常量
    // constants.js
    //export const A = 1;
    //export const B = 2;
    //export const C = 3;

    // test1.js模块
    //import * as constants from 'constants';

}
// 全局对象的属性
var a = 1;
console.log(window.a);  // 1

let b = 2;
console.log(window.b);  // undefined

二、字符串

{
    // 使用for of循环字符串
    for (let c of 'foo') {
        console.log(c);
    }

    let s = 'Hello world!';

    // 使用字符串的startsWidth/endsWidth/includes方法
    console.log(s.startsWith('Hello')); // true
    console.log(s.endsWith('!'));   // true
    console.log(s.includes('e'));   // true

    // 这三个方法都支持第二个参数,表示开始搜索的位置
    s.startsWith('world', 6);   // true

    let person = {
        name: 'king',
        age: 20
    };

    // 模板字符串
    // 所有的空格和缩进都会被保留在输出中
    let str = (`
        The name is ${person.name}.
        The age is ${person.age}.
    `);

    console.log(str);

}

三、函数

// 函数参数的默认值
function log(x, y = 'world') {
    console.log(x, y);
}

log('hello');   // 可以省略尾部参数的默认值

function f(x = 1, y) {
    return [x, y];
}

f();    // [1, undefined]
f(2);   // [2, undefined]
f(, 1); // 报错, 编译无法通过

// rest参数
function add(...values) {
    let sum = 0;

    for (let val of values) {
        sum += val;
    }

    return sum;
}

console.log(add(2, 5, 3));   // 10

const sortNumbers = function() {
    let arr = Array.prototype.slice.call(arguments);
    return arr.sort();
};

const sortNumbers = function (...numbers) {
    return numbers.sort();
};

sortNumbers(3, 1, 2);

// rest参数必须是参数列表中的最后一个
const push = function(array, ...items) {
    items.forEach(function(item) {
        array.push(item);
    });
};

let a = [];

console.log(push(a, 3, 1, 2));

四、对象

// Object.assign方法用来将源对象的所有可枚举属性复制到目标对象
let target = {
    a: 1
};

// 后边的属性值,覆盖前面的属性值
Object.assign(target, {
    b: 2,
    c: 3
}, {
    a: 4
});

console.log(target);

// 用处1 - 为对象添加属性
class Point {
    constructor(x, y) {
        Object.assign(this, {x, y});
    }
}

//let p = new Point(1, 2);
//
//console.log(p); // Point {x: 1, y: 2}

// 用处2 - 为对象添加方法
Object.assign(Point.prototype, {
    getX() {
        return this.x;
    },
    setX(x) {
        this.x = x;
    }
});

let p = new Point(1, 2);

console.log(p.getX());  // 1

// 用处3 - 克隆对象
function clone(origin) {
    return Object.assign({}, origin);
}

五、Set和Map

  // Set里面的成员的值都是唯一的,没有重复的值,Set加入值时不会发生类型转换,所以5和"5"是两个不同的值.
    let s = new Set();

    [2, 3, 5, 4, 5, 2, 2].map(function(x) {
        s.add(x);
    });

    //for (let i of s) {
    //    console.log(i);
    //}

    console.log([...s]);

    console.log(s.size);

    // 数组去重
    function dedupe(array) {
        return Array.from(new Set(array));
    }

    console.log(dedupe([1, 2, 2, 3]));  // 1, 2, 3
{

    // Map类似于对象,也是键值对的集合,但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当做键.
    // 也就是说,Object结构提供了"字符串--值"的对应,Map的结构提供了"值——值"的对象,是一种更完善的Hash结构实现.

    var m = new Map();

    var o = {
        p: 'Hello World'
    };

    m.set(o, 'content');
    m.get(o);   // content

    m.has(o);    // true
    m.delete(o);    // true
    m.has(o);   // false

    m.set(o, 'my content').set(true, 7).set('foo', 8);

    console.log(m);

    // Map/数组/对象 三者之间的相互转换
    console.log([...m]);

}

六、Iterator和Generator

{
    // 是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构,只要不输Iterator接口,就可以完成遍历操作.
    // 可供for...of循环消费

    const arr = ['red', 'green', 'blue'];

    let iterator = arr[Symbol.iterator]();

    for (let v of arr) {
        console.log(v); // red green blue
    }

    for (let i of iterator) {
        console.log(i);
    }

    // for of 循环可以代替数组对象的forEach方法, 同样可以替代对象的for in循环

}
{
    function * foo() {
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
        return 6;
    }

    for (let v of foo()) {
        console.log(v);
    }

}

七、Promise和async

{
    let getJSON = function (path, param) {

        return new Promise(function(resolve, reject) {
            let async = typeof param.async == 'undefined' ? true : param.async;
            //let deferred = $.Deferred();

            param = param || {};
            param.data.auth_token = lib.getToken();

            window.loading();

            $.ajax({
                url: path,
                data: param.data,
                type: 'POST',
                dataType: 'json',
                async: async,
                timeout: 15000,
                success: function (data) {
                    window.unloading();
                    if (data.code == 0) {
                        resolve.apply(this, [data]);
                    } else {
                        reject.apply(this, [data]);
                        lib.alert(data.msg, '我知道了');
                    }
                },
                error: function (xhr, type) {
                    window.unloading();
                    reject.apply(this, ['网络异常, 请稍候再试']);
                    lib.alert('网络异常, 请稍候再试');
                }
            });
        });

    };

    getJSON('/xxx.json').then(function(rep) {

    }).catch(function(rep) {

    });

}
{

    function timeout(ms) {
        return new Promise(function(resolve) {
            setTimeout(resolve, ms);
        });
    }

    async function asyncPrint(value, ms) {
        let promise = await timeout(ms);
        console.log(value);
    }

    asyncPrint('Hello world !', 1000);

}

八、class

{
    class Point {

        static classMethod() {
            return 'classMethod...';
        }

        // constructor方法是类的默认方法,通过new命令生成对象实例时自动调用该方法.
        // 一个类必须有constructor方法,如果没有显示定义,一个空的constructor方法会被默认添加
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }

        toString() {
            return '(' + this.x + ', ' + this.y + ')';
        }

        get prop() {
            return 'getter';
        }

        set prop(value) {
            console.log('setter:' + value);
        }

    }

    // 静态属性的处理,只能用下面这种方式
    Point.foo = 1;
    console.log(Point.foo); // 1

    // 继承
    class ColorPoint extends Point {

        constructor(x, y, color) {
            // super方法必须被调用, 否则编译不通过
            // 如果super在赋值属性this.xx = xx,后边调用,会报错'this' is not allowed before super()
            super(x, y);
            this.color = color;
        }

        toString() {
            return 'The color is ' + this.color + ' and the point is ' + super.toString();
        }

    }

    var p = new ColorPoint(1, 2, 'red');
    console.log(p.toString());
    p.prop = 1;
    p.prop;

    console.log(Point.classMethod());

    // 父类的静态方法可以被子类继承
    console.log('ColorPoint.classMethod(): ' + ColorPoint.classMethod());

}

九、Module

{
    // module
    /**
     * 优势:
     *  1. ES6可以在编译时就完成模块编译,效率要比commonJs模块的加载方式高
     *  2. 不再需要UMD模块格式,将来服务器端和浏览器都会支持ES6模块格式.目前,通过各种工具库其实已经做到了这一点
     *  3. 将来浏览器的新API可以用模块格式提供,不再需要做成全局变量或者navigator对象的属性
     *  4. 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供
     */

}
// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};

// export命令除了输出变量,还可以输出函数或类(class)。
export function multiply (x, y) {
    return x * y;
};

// export输出的变量就是本来的名字,但是可以使用as关键字重命名。

function v1() {
    //...
}
function v2() {
    //...
}

export {
    v1 as streamV1,
    v2 as streamV2,
    v2 as streamLatestVersion
};

// import
// main.js

import {firstName, lastName, year} from './profile';

// 重命名
import { lastName as surname } from './profile';

// import命令具有提升效果,会提升到整个模块的头部,首先执行。
foo();
import { foo } from 'my_module';

// 仅仅执行lodash模块,但是不输入任何值。
import 'lodash';

// export default
// 为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

// export-default.js
export default function () {
    console.log('foo');
}

// import-default.js
// 需要注意,这时import命令后面,不使用大括号。
import customName from './export-default';
customName(); // 'foo'

// export default命令用在非匿名函数前,也是可以的。
// export-default.js
export default function foo() {
    console.log('foo');
}

// 或者写成

function foo() {
    console.log('foo');
}

export default foo;
十、编程风格
// 1. let取代var


// 2. 全局常量
// 在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。
// const声明常量还有两个好处,一是阅读代码的人立刻会意识到不应该修改这个值,二是防止了无意间修改变量值所导致的错误。
// 所有的函数都应该设置为常量。

// bad
var a = 1, b = 2, c = 3;

// good
const a = 1;
const b = 2;
const c = 3;

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


// 3. 字符串
// 静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。


// 4. 对象
//对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法。
// bad
const a = {};
a.x = 3;

// if reshape unavoidable
const a = {};
Object.assign(a, { x: 3 });

// good
const a = { x: null };
a.x = 3;

// 对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。

var ref = 'some value';

// bad
const atom = {
    ref: ref,

    value: 1,

    addValue: function (value) {
        return atom.value + value;
    },
};

// good
const atom = {
    ref,

    value: 1,

    addValue(value) {
        return atom.value + value;
    },
};


// 5. 数组
//使用扩展运算符(...)拷贝数组。

// bad
const len = items.length;
const itemsCopy = [];
let i;

for (i = 0; i < len; i++) {
    itemsCopy[i] = items[i];
}

// good
const itemsCopy = [...items];

//使用Array.from方法,将类似数组的对象转为数组。

const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);

// 6. 函数
//不要在函数体内使用arguments变量,使用rest运算符(...)代替。因为rest运算符显式表明你想要获取参数,而且arguments是一个类似数组的对象,而rest运算符可以提供一个真正的数组。

// bad
function concatenateAll() {
    const args = Array.prototype.slice.call(arguments);
    return args.join('');
}

// good
function concatenateAll(...args) {
    return args.join('');
}

//使用默认值语法设置函数参数的默认值。

// bad
function handleThings(opts) {
    opts = opts || {};
}

// good
function handleThings(opts = {}) {
    // ...
}

// 7. 模块
//首先,Module语法是JavaScript模块的标准写法,坚持使用这种写法。使用import取代require。

// bad
const moduleA = require('moduleA');
const func1 = moduleA.func1;
const func2 = moduleA.func2;

// good
import { func1, func2 } from 'moduleA';

//使用export取代module.exports。

// commonJS的写法
var React = require('react');

var Breadcrumbs = React.createClass({
    render() {
        return <nav />;
    }
});

module.exports = Breadcrumbs;

// ES6的写法
import React from 'react';

const Breadcrumbs = React.createClass({
    render() {
        return <nav />;
    }
});

export default Breadcrumbs
//如果模块只有一个输出值,就使用export default,如果模块有多个输出值,就不使用export default,不要export default与普通的export同时使用。

//不要在模块输入中使用通配符。因为这样可以确保你的模块之中,有一个默认输出(export default)。

// bad
import * as myObject './importModule';

// good
import myObject from './importModule';
//如果模块默认输出一个函数,函数名的首字母应该小写。

function makeStyleGuide() {
}

export default makeStyleGuide;
//如果模块默认输出一个对象,对象名的首字母应该大写。

const StyleGuide = {
    es6: {
    }
};

export default StyleGuide;

ES6扫盲的更多相关文章

  1. ES6 扫盲

    原文地址:ECMAScript 6 扫盲--小胡子 1. let.const 和 block 作用域 let 允许创建块级作用域,ES6 推荐在函数中使用 let 定义变量,而非 var: var a ...

  2. 深度扫盲JavaScript的模块化(AMD , CMD , CommonJs 和 ES6)

    原文地址 https://blog.csdn.net/haochangdi123/article/details/80408874 一.commonJS 1.内存情况 对于基本数据类型,属于复制.即会 ...

  3. ECMAScript 6 扫盲

    ECMAScript 6 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中 ...

  4. 前端MVC Vue2学习总结(七)——ES6与Module模块化、Vue-cli脚手架搭建、开发、发布项目与综合示例

    使用vue-cli可以规范项目,提高开发效率,但是使用vue-cli时需要一些ECMAScript6的知识,特别是ES6中的模块管理内容,本章先介绍ES6中的基础与模块化的内容再使用vue-cli开发 ...

  5. 听闰土大话前端之ES6是怎么来的

    前言 相信做前端的朋友没有不知道ECMAScript6的,都知晓ES6新增了不少新的特性,但是你知道ES6是怎么来的吗?今天就让闰土来带大家大话ES6的前世今生.当然了,这篇文章会以扫盲为主,科普为辅 ...

  6. 120分钟React快速扫盲教程

    在教程开端先说些题外话,我喜欢在学习一门新技术或读过一本书后,写一篇教程或总结,既能帮助消化,也能加深印象和发现自己未注意的细节,写的过程其实仍然是一个学习的过程.有个记录的话,在未来需要用到相关知识 ...

  7. 常用的ES6语法

    1. let.const 和 block 作用域 let 允许创建块级作用域,ES6 推荐在函数中使用 let 定义变量,而非 var: var a = 2; { let a = 3; console ...

  8. ES6深入浅出_汇总贴

    H:\BaiDu\ES6深入浅出-wjw ES 6 新特性一览:https://frankfang.github.io/es-6-tutorials/ 我用了两个月的时间才理解 let https:/ ...

  9. JavaScript学习总结(七)——ECMAScript6(ES6)

    一.ECMAScript概要 ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通 ...

随机推荐

  1. ASE周会记录

    本周Sprint Master Atma Hou 一. 本周会议概要 本次会议的主要任务是明确和老师讨论后的数据库设计定稿,同时为我们接下来的连接工作确定包含实现细节的story和接口. 二. 会议内 ...

  2. setTimeout 和 throttle 那些事儿

    document.querySelector('#settimeout').onclick= function () { setTimeout(function () { console.log('t ...

  3. The commands of Disk

    The commands of Disk fdisk( the disk size is less 2TB) fdisk - partition table manipulator for Linux ...

  4. web应用中浏览器与服务端的编码和解码

    转自:http://blog.sina.com.cn/s/blog_87cb63e50102w2b6.html 以下为正文: ************************************* ...

  5. excellent cushioning and also vitality go back with this boot

    The particular manufactured fine mesh higher almost addresses the complete boot. Here is the sort of ...

  6. jquery 返回顶部 兼容web移动

    返回顶部图片 http://hovertree.com/texiao/mobile/6/tophovertree.gif 具体实现代码 <span id="tophovertree&q ...

  7. iPhone屏幕尺寸/launch尺寸/icon尺寸

    屏幕尺寸 6p/6sp     414 X 736 6/6s         375 X 667 5/5s         320 X 568  4/4s         320 X 480   la ...

  8. hibernate学习二(HelloWorld)

    一.建立hibernate配置文件 在工程Hibernate_01_HelloWorld下的src上建立hibernate.cfg.xml,打开hibernate-release-4.3.11.Fin ...

  9. Python:基本语法1

    I.Python中的转义符注意情况 如果'本身是一个字符,则可将其用" "括起来: 如果字符串内部既有',又有",则可用转义字符\,比如: 'I\'m\"OK\ ...

  10. fedora配置163为yum的源

    一种方法: 1.下载  http://mirrors.163.com/.help/fedora-163.repo 和 http://mirrors.163.com/.help/fedora-updat ...