• es6涉及的那点东西


    前言

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。
    也就是说,ES6就是ES2015。
    目前并不是所有浏览器都能兼容ES6全部特性,我们可以使用Babel工具来转换成es5
    Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码

    最常用的ES6特性
    let, const, class, extends, super, arrow functions, template string, destructuring, default, rest arguments

    一、let 、const命令

    1、let用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效
    2、不存在变量提升,let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。

    console.log(foo); // 输出undefined
    console.log(bar); // 报错ReferenceError
    var foo =2;let bar =2;
    

    3、在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

    const声明常量还有两个好处,一是阅读代码的人立刻会意识到不应该修改这个值,二是防止了无意间修改变量值所导致的错误。

    4、ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
    总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。也就是“暂时性死区”。

    二、es6模块(module)

    JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如Ruby的require、Python的import,甚至就连CSS都有@import,但是JavaScript任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。

    这有可能导致两个问题:

    • 一方面js代码变得很臃肿,难以维护
    • 另一方面我们常常得很注意每个script标签在html中的位置,因为它们通常有依赖关系,顺序错了可能就会出bug
    • 在es6之前为解决上面提到的问题,我们得利用第三方提供的一些方案,主要有两种CommonJS(服务器端)和AMD(浏览器端,如require.js)。

    在ES6之前,社区制定了一些模块加载方案,最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。ES6在语言规格的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。

    传统的写法
    首先我们回顾下require.js的写法。假设我们有两个js文件: index.js和content.js,现在我们想要在index.js中使用content.js返回的结果,我们要怎么做呢?
    首先定义:

    //content.js
    define('content.js', function(){
        return'A cat';
    })
    

    然后require:

    //index.js
    require(['./content.js'], function(animal){
        console.log(animal);   //A cat
    })
    

    CommonJS写法

    //index.js
    var animal = require('./content.js')
    
    //content.js
    module.exports = 'A cat'
    

    ES6的写法

    //index.js
    import animal from'./content'//content.js
    export default'A cat'
    

    // ES6模块

    import { stat, exists, readFile } from 'fs';
    

    上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”,即ES6可以在编译时就完成模块加载,效率要比CommonJS模块的加载方式高。当然,这也导致了没法引用ES6模块本身,因为它不是对象。

    浏览器使用ES6模块的语法如下。

    <script type="module" src="foo.js"></script>
    

    上面代码在网页中插入一个模块foo.js,由于type属性设为module,所以浏览器知道这是一个ES6模块。

    Node的默认模块格式是CommonJS,目前还没决定怎么支持ES6模块。所以,只能通过Babel这样的转码器,在Node里面使用ES6模块。

    ES6的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。

    1、export命令

    模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
    一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。例如,

    // 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;};
    

    可以使用as关键字重命名

    function v1(){...}
    function v2(){...}
    
    export {
      v1 as streamV1,
      v2 as streamV2,
      v2 as streamLatestVersion
    };
    

    注意:export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,import命令也是如此,这是因为处于条件代码块之中,就没法做静态优化了,违背了ES6模块的设计初衷。下面代码中,export语句放在函数之中,结果报错。

    function foo(){
      export default 'bar' // SyntaxError
    }
    foo()
    

    2、import命令

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

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

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

    使用as关键字将输入的变量重新命名

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

    import命令具有提升效果,会提升到整个模块的头部,首先执行。

    foo();
    
    import { foo } from 'my_module';
    

    上面的代码不会报错,因为import的执行早于foo的调用。

    import语句会执行所加载的模块,但是不输入任何值。

    import 'lodash';
    

    import 也可以引用文件夹/目录

    如import router from './router' 
    

    这里router是个目录 里面有个index.js文件

    3、模块整体加载

    circle模块有2个方法

    // circle.js
    
    export function area(radius){return Math.PI * radius * radius;}
    
    export function circumference(radius){return2* Math.PI * radius;}
    
    通过使用*号加载整个模块
    import * as circle from './circle';
    
    console.log('圆面积:'+ circle.area(4));
    console.log('圆周长:'+ circle.circumference(14));
    

    三、class类

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

    //定义类
    class Point{
      constructor(x, y){
        this.x = x;
        this.y = y;
      }
      toString(){
        return'('+this.x +', '+this.y +')';
      }
    }
    

    constructor这就是构造方法,而this关键字则代表实例对象
    定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。

    使用时直接对类使用new命令

    class Bar{
      doStuff(){
        console.log('stuff');
      }
    }
    
        var b =new Bar();
    b.doStuff() // "stuff"
    

    2、constructor构造方法

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

    3、class表达式

    与函数一样,类也可以使用表达式的形式定义。

    const MyClass = class Me{
      getClassName(){
        return Me.name;
      }
    };
    

    这个类的名字是MyClass而不是Me,Me只在Class的内部代码可用,指代当前类。

    如果类的内部没用到的话,可以省略Me

    const MyClass = class {/* ... */};
    

    采用Class表达式,可以写出立即执行的Class。

    let person =newclass{
      constructor(name){
        this.name = name;
      }
      sayName(){
        console.log(this.name);
      }
    }('张三');
    
    person.sayName(); // "张三"
    

    4、class类继承

    通过extends关键字实现继承

    class ColorPoint extends Point{}
    

    四、arrow function箭头函数

    function(i){ 
      return i + 1; 
    } //ES5
    (i) => i + 1//ES6
    

    如果方程比较复杂,则需要用{}把代码包起来:

    function(x, y){ 
        x++;
        y--;
        return x + y;
    }
    (x, y) => {
      x++; y--; 
      return x+y
    }
    

    在对象方法中使用this

    传统的写法需要将this传给self,再用self来指代this

     says(say){
           var self = this;
           setTimeout(function(){
               console.log(self.type + ' says ' + say)
           }, 1000)
    

    使用es6的写法

    classAnimal {
        constructor(){
            this.type = 'animal'
        }
        says(say){
            setTimeout( () => {
                console.log(this.type + ' says ' + say)
            }, 1000)
        }
    }
     var animal = new Animal()
     animal.says('hi')  //animal says hi
    

    当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。

    五、template string

    当我们要插入大段的html内容到文档中时,传统的写法非常麻烦,所以之前我们通常会引用一些模板工具库,比如mustache等等

    $("#result").append(
      "There are <b>" + basket.count + "</b> " +
      "items in your basket, " +
      "<em>" + basket.onSale +
      "</em> are on sale!"
    );
    

    我们要用一堆的'+'号来连接文本与变量,而使用ES6的新特性模板字符串``后

    $("#result").append(`
      There are <b>${basket.count}</b> items
       in your basket, <em>${basket.onSale}</em>
      are on sale!
    `);
    

    用反引号()来标识起始,用${}`来引用变量,而且所有的空格和缩进都会被保留在输出之中

    六、default, rest

    default很简单,意思就是默认值,调用animal()方法时忘了传参数,传统的做法就是加上这一句type = type || 'cat' 来指定默认值

    function animal(type){
        type = type || 'cat'  
        console.log(type)
    }
    animal()
    

    用ES6我们而已直接这么写:

    function animal(type = 'cat'){
        console.log(type)
    }
    animal()
    

    rest语法也很简单,看例子:

    function animals(...types){
        console.log(types)
    }
    animals('cat', 'dog', 'fish') //["cat", "dog", "fish"]
    

    参考阅读

    https://segmentfault.com/a/1190000004365693#articleHeader7
    http://es6.ruanyifeng.com/

  • 相关阅读:
    ES6-01 2018-02-06
    8.1 IO类
    2.4 const限定符
    C++命名空间
    win7系统docker安装ubuntu
    win7安装docker
    wuzhicms 查看模板中的所有可用变量和值
    wuzhicms上传弹出层,如何返回数据到当前页面?
    wuzhicms 无规律推荐位标签的嵌套使用
    【wuzhicms】apache 设置禁止访问某些文件或目录
  • 原文地址:https://www.cnblogs.com/fozero/p/10417855.html
Copyright © 2020-2023  润新知