• 【学习笔记】ES6标准入门


    这里简要记录一下对自己感触比较深的几个知识点,将核心的应用投放于实际的项目之中,提供代码的可维护性。

    一、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;

    希望我所记录的,正是你所想要的。 

    最后,将这本书的封面放在这里——



  • 相关阅读:
    php报表之jpgraph柱状图实例
    如何不做伪phper
    php如何将图片gif,jpg或mysql longblob或blob字段值转换成16进制字符串!编辑
    PHP解析JSON与XML
    dedeCms登录后台(验证码不正确)解决办法
    php curl用法
    PHP表单验证的3个函数ISSET()、empty()、is_numeric()的使用方法
    SAE学习笔记1
    windows(linuxFedora13)php 发送邮件 (sendmail+PHPMailer) 结合配置问题
    drupal7 常用的数据读取API
  • 原文地址:https://www.cnblogs.com/jinguangguo/p/5245265.html
Copyright © 2020-2023  润新知