zoukankan      html  css  js  c++  java
  • es6

    • classes - 各种 ‘类’,再也无需用 CoffeeScript 的语法糖写类了
    • generators - 未来的.js 代码中将有无数生成器,不学一点就看不懂 JS 代码了哦
    • collections - 集合、映射、弱集合、弱映射
    • arrow functions - 箭向函数
    • block scoping - 使用 let 、const 作用域,块辖域
    • template strings - 模板字串
    • promises - 用标准化了的方法进行延迟和异步计算
    • symbols - 唯一的、不可修改的数据

    string:indexof,includes,startWith(),endWith(),str.repeat()

    模版字符串 ,标签模版

    String.raw()

    1. let raw = String.raw`Not a newline: `;
    2. document.write(raw === 'Not a newline: \n'); // true

    ES6在Number对象上,新提供了Number.isFinite()和Number.isNaN(),Number.isInteger()

    Math.trunc():去除一个数的小数部分,返回整数部分。

    1. Math.trunc(4.1) // 4
    2. Math.trunc(-4.1) // -4

    注意:对于空值和无法截取整数的值,返回NaN。

    Math.sign():判断一个数到底是正数、负数、还是零。

    返回五种值:参数为正数,返回+1;参数为负数,返回-1;参数为0,返回0;参数为-0,返回-0;其他值,返回NaN。

    1. Math.sign(-5) // -1
    2. Math.sign(5) // +1
    3. Math.sign(0) // +0
    4. Math.sign(-0) // -0
    5. Math.sign('hubwiz'); // NaN

    Math.cbrt:计算一个数的立方根。

    1. Math.cbrt(-1); // -1
    2. Math.cbrt(0); // 0
    3. Math.cbrt(2); // 1.2599210498948732

    Math.fround:返回一个数的单精度浮点数形式。

    1. Math.fround(0); // 0
    2. Math.fround(1.337); // 1.3370000123977661
    3. Math.fround(NaN); // NaN

    Math.hypot:返回所有参数的平方和的平方根。

    1. Math.hypot(3, 4); // 5
    2. Math.hypot(3, 4, 5); // 7.0710678118654755
    3. Math.hypot(); // 0
    4. Math.hypot(NaN); // NaN
    5. Math.hypot(3, 4, 'foo'); // NaN
    6. Math.hypot(3, 4, '5'); // 7.0710678118654755
    7. Math.hypot(-3); // 3

    Array

    1. let arrNew = Array.from(array).map(x => x * x);
    2. Array.of
    3. let array = [1, 4, -5, 10].find((n) => n < 0);
    4. let index = [1, 5, 10, 15].findIndex(function(value, index, arr) {return value > 9})
    5. let arr = ['a', 'b', 'c'].fill(7)
      • entries()
      • keys()
      • values()

     for (let index of ['a', 'b'].keys()) {document.write(index);}

    for (let elem of ['a', 'b'].values()) {document.write(elem);}

    for (let [index, elem] of ['a', 'b'].entries()) {document.write(index, elem);}

    表达式属性和表达式方法名

    let propKey = 'foo';

    let obj = {

         [propKey]: true,

        ['a'+'bc']: 123

    };

    let obj = {

           ['h'+'ello']() {

                 return 'hi';

            }

    };

    Object.is(+0, -0) // false

    Object.assign()

    1. var target = { a: 1, b: 1 };
    2.  
    3. var source1 = { b: 2, c: 2 };
    4. var source2 = { c: 3 };
    5.  
    6. Object.assign(target, source1, source2);
    7. target // {a:1, b:2, c:3}

    proto属性

    1. // es6的写法
    2.  
    3. var obj = {
    4. __proto__: someOtherObj,
    5. method: function() { ... }
    6. }
    7.  
    8. // es5的写法
    9.  
    10. var obj = Object.create(someOtherObj);
    11. obj.method = function() { ... }

    proxy

    函数;默认参数,不定参数...rest简称rest参数,参数数组

     扩展运算符 ...ares

    箭头函数,箭头函数里没有this

    函数绑定

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

    1. let log = ::console.log;
    2. // 等同于
    3. var log = console.log.bind(console);
    4.  
    5. foo::bar;
    6. // 等同于
    7. bar.call(foo);
    8.  
    9. foo::bar(...arguments);
    10. i// 等同于
    11. bar.apply(foo, arguments);

    set  weakSet和map weakmap

    Symbol   

    Iterator 

    Generator  Generator函数是一个函数的内部状态的遍历器

    Generator函数是一个普通函数,但是有两个特征。

    • 一是,function命令与函数名之间有一个星号;
    • 二是,函数体内部使用yield语句,定义遍历器的每个成员,即不同的内部状态。
    1. function* fibonacci() {
    2. let [prev, curr] = [0, 1];
    3. for (;;) {
    4. [prev, curr] = [curr, prev + curr];
    5. yield curr;
    6. }
    7. }
    8.  
    9. for (let n of fibonacci()) {
    10. if (n > 1000) break;
    11. document.write(n);
    12. }

    可以从函数体外面控制循环

    Generator 函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。

    1. function* gen(x){
    2. try {
    3. var y = yield x + 2;
    4. } catch (e){
    5. document.write(e);
    6. }
    7. return y;
    8. }
    9.  
    10. var g = gen(1);
    11. g.next();
    12. g.throw'出错了');
    13. // 出错了

    上面代码的最后一行,Generator 函数体外,使用指针对象的 throw 方法抛出的错误,可以被函数体内的 try ... catch 代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。

    如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。

    promise

    1. //创建promise
    2. var promise = new Promise(function(resolve, reject) {
    3. // 进行一些异步或耗时操作
    4. if ( /*如果成功 */ ) {
    5. resolve("Stuff worked!");
    6. } else {
    7. reject(Error("It broke"));
    8. }
    9. });
    10. //绑定处理程序
    11. promise.then(function(result) {
    12. //promise成功的话会执行这里
    13. document.write(result); // "Stuff worked!"
    14. }, function(err) {
    15. //promise失败会执行这里
    16. document.write(err); // Error: "It broke"
    17. });

    catch方法

    1. getJSON("/posts.json").then(function(posts) {
    2. // ...
    3. }).catch(function(error) {
    4. // 处理前一个回调函数运行时发生的错误
    5. document.write('发生错误!', error);
    6. });
    1. var promise = new Promise(function(resolve, reject) {
    2. throw new Error('test')
    3. });
    4. promise.catch(function(error) { document.write(error) });
    5. // Error: test
    1. getJSON("/post/1.json").then(function(post) {
    2. return getJSON(post.commentURL);
    3. }).then(function(comments) {
    4. // some code
    5. }).catch(function(error) {
    6. // 处理前面三个Promise产生的错误
    7. });

    promise.all

    1. // 生成一个Promise对象的数组
    2. var promises = [2, 3, 5, 7, 11, 13].map(function(id){
    3. return getJSON("/post/" + id + ".json");
    4. });
    5.  
    6. Promise.all(promises).then(function(posts) {
    7. // ...
    8. }).catch(function(reason){
    9. // ...
    10. });

    Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。

    1. var p = Promise.race([p1,p2,p3]);

    上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数。

    使用Generator函数管理流程,遇到异步操作的时候,通常返回一个Promise对象。

    1. function getFoo () {
    2. return new Promise(function (resolve, reject){
    3. resolve('foo');
    4. });
    5. }
    6.  
    7. var g = function* () {
    8. try {
    9. var foo = yield getFoo();
    10. document.write(foo);
    11. } catch (e) {
    12. document.write(e);
    13. }
    14. };
    15.  
    16. function run (generator) {
    17. var it = generator();
    18.  
    19. function go(result) {
    20. if (result.done) return result.value;
    21.  
    22. return result.value.then(function (value) {
    23. return go(it.next(value));
    24. }, function (error) {
    25. return go(it.throw(value));
    26. });
    27. }
    28.  
    29. go(it.next());
    30. }
    31.  
    32. run(g);

    async函数与Promise、Generator函数一样,是用来取代回调函数、解决异步操作的一种方法。

    async函数与Promise、Generator函数一样,是用来取代回调函数、解决异步操作的一种方法。

    async函数,就是下面这样。

    1. var asyncReadFile = async function (){
    2. var f1 = await readFile('/etc/fstab');
    3. var f2 = await readFile('/etc/shells');
    4. document.write(f1.toString());
    5. document.write(f2.toString());
    6. };

    async函数对Generator函数的改进,体现在以下三点。

    • 内置执行器。Generator函数的执行必须靠执行器,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
      1. var result = asyncReadFile();
    • 更好的语义。async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
    • 更广的适用性。co函数库约定,yield命令后面只能是Thunk函数或Promise对象,而async函数的await命令后面,可以跟Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。

    calss

    Class的继承


    Class之间可以通过extends关键字,实现继承。

    子类会继承父类的属性和方法。

    1. class Point {
    2. constructor(x, y) {
    3. this.x = x;
    4. this.y = y;
    5. }
    6. }
    7.  
    8. class ColorPoint extends Point {
    9. constructor(x, y, color) {
    10. this.color = color; // ReferenceError
    11. super(x, y);
    12. this.color = color; // 正确
    13. }
    14. }

    上面代码中,子类的constructor方法没有调用super之前,就使用this关键字,结果报错,而放在super方法之后就是正确的。

    注意:ColorPoint继承了父类Point,但是它的构造函数必须调用super方法。

    下面是生成子类实例的代码。

    1. let cp = new ColorPoint(25, 8, 'green');
    2.  
    3. cp instanceof ColorPoint // true
    4. cp instanceof Point // true

    Class的Generator方法


    如果某个方法之前加上星号(*),就表示该方法是一个Generator函数。

    1. class Foo {
    2. constructor(...args) {
    3. this.args = args;
    4. }
    5. * [Symbol.iterator]() {
    6. for (let arg of this.args) {
    7. yield arg;
    8. }
    9. }
    10. }
    11.  
    12. for (let x of new Foo('hello', 'world')) {
    13. document.write(x);
    14. }
    15. // hello
    16. // world

    上面代码中,Foo类的Symbol.iterator方法前有一个星号,表示该方法是一个Generator函数。Symbol.iterator方法返回一个Foo类的默认遍历器,for...of循环会自动调用这个遍历器。

    Class的静态方法


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

    1. class Foo {
    2. static classMethod() {
    3. return 'hello';
    4. }
    5. }
    6. Foo.classMethod() // 'hello'
    7. var foo = new Foo();
    8. foo.classMethod()
    9. // TypeError: undefined is not a function

    上面代码中,Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。

    父类的静态方法,可以被子类继承。

    1. class Foo {
    2. static classMethod() {
    3. return 'hello';
    4. }
    5. }
    6. class Bar extends Foo {
    7. }
    8. Bar.classMethod(); // 'hello'

    上面代码中,父类Foo有一个静态方法,子类Bar可以调用这个方法。

    静态方法也是可以从super对象上调用的。

    1. class Foo {
    2. static classMethod() {
    3. return 'hello';
    4. }
    5. }
    6. class Bar extends Foo {
    7. static classMethod() {
    8. return super.classMethod() + ', too';
    9. }
    10. }
    11. Bar.classMethod();

    new.target属性


    new是从构造函数生成实例的命令。ES6为new命令引入了一个new.target属性,(在构造函数中)返回new命令作用于的那个构造函数。如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的。

    1. function Person(name) {
    2. if (new.target !== undefined) {
    3. this.name = name;
    4. } else {
    5. throw new Error('必须使用new生成实例');
    6. }
    7. }
    8.  
    9. // 另一种写法
    10. function Person(name) {
    11. if (new.target === Person) {
    12. this.name = name;
    13. } else {
    14. throw new Error('必须使用new生成实例');
    15. }
    16. }
    17.  
    18. var person = new Person('张三'); // 正确
    19. var notAPerson = Person.call(person, '张三'); // 报错

    上面代码确保构造函数只能通过new命令调用。

    • Class内部调用new.target,返回当前Class。
    • 子类继承父类时,new.target会返回子类。

    修饰器-类的修饰


    修饰器(Decorator)是一个表达式,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经支持。

    修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。

    1. function testable(target) {
    2. target.isTestable = true;
    3. }
    4. @testable
    5. class MyTestableClass {}
    6. console.log(MyTestableClass.isTestable) // true

    上面代码中,@testable就是一个修饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。

    基本上,修饰器的行为就是下面这样。

    1. @decorator
    2. class A {}
    3.  
    4. // 等同于
    5.  
    6. class A {}
    7. A = decorator(A) || A;

    也就是说,修饰器本质上就是能在编译时执行的函数

    修饰器-类的修饰


    修饰器函数可以接受三个参数,依次是目标函数、属性名和该属性的描述对象。后两个参数可省略。上节修饰器-类的修饰1代码中,testable函数的参数target,就是所要修饰的对象。如果希望修饰器的行为,能够根据目标对象的不同而不同,就要在外面再封装一层函数。

    1. function testable(isTestable) {
    2. return function(target) {
    3. target.isTestable = isTestable;
    4. }
    5. }
    6.  
    7. @testable(true) class MyTestableClass () {}
    8. document.write(MyTestableClass.isTestable) // true
    9.  
    10. @testable(false) class MyClass () {}
    11. document.write(MyClass.isTestable) // false

    如果想要为类的实例添加方法,可以在修饰器函数中,为目标类的prototype属性添加方法。

    1. function testable(target) {
    2. target.prototype.isTestable = true;
    3. }
    4.  
    5. @testable
    6. class MyTestableClass () {}
    7.  
    8. let obj = new MyClass();
    9.  
    10. document.write(obj.isTestable) // true

    export命令


    模块功能主要由两个命令构成:export和import。

    • export命令用于用户自定义模块,规定对外接口;
    • import命令用于输入其他模块提供的功能,同时创造命名空间(namespace),防止函数名冲突。

    ES6允许将独立的JS文件作为模块,允许一个JavaScript脚本文件调用另一个脚本文件。

    现有profile.js文件,保存了用户信息。ES6将其视为一个模块,里面用export命令对外部输出了三个变量。

    1. // profile.js
    2. var firstName = 'Michael';
    3. var lastName = 'Jackson';
    4. var year = 1958;
    5.  
    6. export {firstName, lastName, year};

    import命令


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

    1. // main.js
    2. import {firstName, lastName, year} from './profile';
    3.  
    4. function sfirsetHeader(element) {
    5. element.textContent = firstName + ' ' + lastName;
    6. }

    上面代码属于另一个文件main.js,import命令就用于加载profile.js文件,并从中输入变量。import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

    如果想为输入的变量重新取一个名字,import语句中要使用as关键字,将输入的变量重命名。

    1. import { lastName as surname } from './profile';

    ES6支持多重加载,即所加载的模块中又加载其他模块。

    export命令除了输出变量,还可以输出方法或类(class)。下面是一个circle.js文件,它输出两个方法area和circumference。

    1. // circle.js
    2. export function area(radius) {
    3. return Math.PI * radius * radius;
    4. }
    5. export function circumference(radius) {
    6. return 2 * Math.PI * radius;
    7. }

    然后,main.js输入circlek.js模块。

    1. // main.js
    2. import { area, circumference } from 'circle';
    3. document.write("圆面积:" + area(4));
    4. document.write("圆周长:" + circumference(14));

    上面写法是逐一指定要输入的方法。另一种写法是整体输入。

    1. import * as circle from 'circle';
    2. document.write("圆面积:" + circle.area(4));
    3. document.write("圆周长:" + circle.circumference(14));

    module命令


    module命令可以取代import语句,达到整体输入模块的作用。

    1. // main.js
    2. module circle from 'circle';
    3.  
    4. document.write("圆面积:" + circle.area(4));
    5. document.write("圆周长:" + circle.circumference(14));

    module命令后面跟一个变量,表示输入的模块定义在该变量上。

    export default命令


    为加载模块指定默认输出,使用export default命令。

    1. // export-default.js
    2. export default function () {
    3. document.write('foo');
    4. }

    上面代码是一个模块文件export-default.js,它的默认输出是一个函数。

    其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

    1. // import-default.js
    2. import customName from './export-default';
    3. customName(); // 'foo'

    上面代码的import命令,可以用任意名称指向export-default.js输出的方法。需要注意的是,这时import命令后面,不使用大括号。

    模块的继承


    模块之间也可以继承。

    假设有一个circleplus模块,继承了circle模块。

    1. // circleplus.js
    2.  
    3. export * from 'circle';
    4. export var e = 2.71828182846;
    5. export default function(x) {
    6. return Math.exp(x);
    7. }

    上面代码中的“export *”,表示输出circle模块的所有属性和方法,export default命令定义模块的默认方法。

    这时,也可以将circle的属性或方法,改名后再输出。

    1. // circleplus.js
    2.  
    3. export { area as circleArea } from 'circle';

    上面代码表示,只输出circle模块的area方法,且将其改名为circleArea。

    加载上面模块的写法如下。

    1. // main.js
    2.  
    3. module math from "circleplus";
    4. import exp from "circleplus";
    5. document.write(exp(math.pi));

    上面代码中的"import exp"表示,将circleplus模块的默认方法加载为exp方法。

  • 相关阅读:
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    lambda表达式
    VIM--保存和退出等命令
  • 原文地址:https://www.cnblogs.com/mttcug/p/8119317.html
Copyright © 2011-2022 走看看