是时候复习一下ES6了--声明用关键字篇

210 阅读9分钟

前言

说是ES6,主要是包含了ES6以及之后的所有的内容的学习和汇总。不定期更新文内容。现在开始吧。

正文

ES6之中,新的关键,新的概念为我们的JS编写带来了更多的可能和更加优秀的性能。

1. let关键字:

  • 用于生命变量,和var的区别在于申明变量的作用域,var声明的作用域是全局的,let申明的变量作用域是块级作用域。最主要的体现就在于循环之中,我们需要通过循环基数(即index)来做些什么的时候,再使用var申明的时候我们的常常使用自运行函数来解决这一问题,但是使用let之后,js会自动的帮我们确定当前循环的变量基数的运行区间,不再会受到全局的影响。
  • let不再存在变量提升的现象,必须声明之后在使用。 这一效果的实现方式是展示性死区,再JS解析到当前代码段之中有通过let申明的变量,则再这一变量声明的代码真正执行之前的区域就是对应的死区,死区之中对于当前变量的使用都将会报错。如果再当前区域外通过var声明了全局变量,但是此区域之中有let声明的名称相同的变量则,这一变量再这一区域之中会被封锁,全局同名变量将会没有作用。
  • 同一区域之中不可以声明相同名称的变量。

2. const:

  • 声明常量内容,此类变量一旦声明,则不可以进行修改。const通过保证变量指向的内存区域的对应的数值的不变来达到这一效果的。所以我们可以知道,基础数据类型的变量再声明之后是不可以改变的,但是对象类型的数据,我们在声明之后,变量指向的内存区域数值实际上是一个地址,所以我们还是可以改变对象之中的内容,但是不可以重新声明对象再赋值。如果想要声明的对象也是完全不变的,可以通过Object.freeze方法,来完全的冻结对象。

3. class:

  • 为了缩小js与其他语言之中对象声明的差异,所以ES6之中新增加了class这个关键字。ES5之中我们可以知道,都是申明一个函数然后通过prototype的内容赋值来实现对象构造函数的书写,ES6之中,为了更好的语义化当前的对象申明,我们可以通过class class_Name{../}的形式来申明我们对象内容,使用constructor关键字,来定义这一对象的构造方法,使用function_Name(arguments)的形式来声明对象的方法。方法之间是可以不需要逗号的。这样写实际上就类似于编写一个构造方法,并且再狗仔函数的prototype对象之上添加上我们想要声明的方法。两者的效果是等价的。我们可以看一段代码:
    class Point{
      constructor(x){
        this.x = x;
      }
    
      toString(){
        console.log(this.x);
      }
    }
  • 声明类的时候其中的函数名称可以通过[变量]的形式来定义,最后当前的函数名称将会使用其中变量的值。
  • 我们可以再类的定义之中为变量设置set和get方法,通过使用这两个关键字内容。如下:
    ...
      get prop(){
        return this.prop;
      }
    
      set prop(newValue){
        this.prop = newValue;
      }
    ...
  • 我们也可以通过new class {...}的写法来马上创造一个匿名类的对象内容。如下:
    let h = new class{
      constructor(x){
        this.x = x;
      }
    
      get prop(){
        return this.prop;
      }
    
      set prop(newValue){
        this.prop = newValue;
      }
    
      toString(){
        console.log(this.x);
      }
    }
  • 这样声明的类之中全部都是严格模式的。不需要明确的书写'use strict'。
  • 不会有声明提前的情况发生,我们必须要再使用之前就进行类的声明。
  • 再class的函数声明的时候再前面添加*符号表示的时generator函数(这个概念将会再之后的新概念篇之中说明)
  • 再使用类的声明的时候,如果我们创建的对象使用结构赋值的方式将对象的方法单独获取出来,则要注意了,这个时候方法之中的this指针的指向会变化,会指向运行时上下文(由于严格模式的存在,所以this会时undefined)这点要特别的注意。
  • 最后我们说一下私有方法,在ES6之中并没有对私有方法声明的关键字,所以**约定俗成,我们通过_Name的形式来声明属性和方法。**当然私有属性的表明语法也已经在申请之中,通过#号标识的方式也已经在审核。

4.static

  • 静态方法的声明,在类的方法前面我们使用static关键字的话,当前方法将会时静态的形式只有通过当前的类明来进行调用,有点类似于java之中的静态方法吧。
  • 我们来扒一扒静态方法的声明方式吧,当我们声明类的时候,我们实际上是声明了一个构造方法对象,这个static关键字的效果,ES5之中我们完全可以通过方法对象添加属性的方式来模拟当前的static关键字。
  • 子类继承了父类之后,其实也继承了父类的静态函数,这一点要单独拿出来说明是因为静态函数的特殊性。所以必须说明一下
  • 我们可以通过super关键字来调用父类的静态方法
  • static也可以修饰属性的,静态属性操作的方式实际上和静态方法类似的。

5. extends

  • 类的继承,子类可以通过这个关键字直接继承父类的信息。
  • 我们都注意到constructor关键字,如果子类没有这一方法的话,将会直接继承父类的构造方法,如果写了构造方法的话,可以通过super关键字来进行调用父类的构造方法。
  • 父类的静态方法和参数也会被子类继承的。
  • 这里我们顺带提一点,子类如何去确定继承自哪个父类呢,我们可以通过Object.getPrototypeOf()方法来获取继承的父类。

6. super

  • 其可以当作函数使用也是可以当作对象来使用的。当我们在子类之中需要调用到父类的构造函数的时候,我们可以直接通过使用super()来进行调用。但是我们可以发现,super返回的内容实际上还是子类的实例,所以我们可以理解为其就相当于 父类.prototype.constructor.call(this) (子类实例)
  • 除去在构造函数之中的作用意外,在类的一般方法之中,super指代的变成了父类的原型对象。即相当于父类.prototype了。
  • 最后一种较为特殊的用法是在静态函数之中使用super。这个时候super相当于父类了。

7. import

  • 模块化是一个十分重要的概念,但是JS之中一直没有引入模块话的形式,所以在ES6之中弥补了这一缺憾。ES6的模块话设计思想是尽量的静态化,其模块不是对象,而是通过export来输出的代码,通过import可以对代码进行导入。所以ES6静态加载在编译的时候就已经确定了,效率相对较高。但是这也导致了一个问题,我们没有办法引用模块本身,只能引入我们导出的内容,这是因为模块并不是对象。看一下代码:
    import { stat, exists, readFile } from 'fs';
  • 当我们引入了相关的变量和方法的时候,如果我们想要为这一方法或者变量换一个名称的话,我们可以使用as关键字,代码如下:
    import { firstName, lastName, year } from './profile.js';
  • 说明一下映入的对应API的使用是需要注意,不能对其进行修改,否则将会报错。
  • import 引入代码有提升性,其在编译的时候会自动的提升到代码头进行执行。
  • import 由于是静态执行的所以其中不能含有任何的表达式。
  • import会自动的执行导入的模块,如果我们只是需要执行模块但是不需要导入任何的数据和方法的话,我们可以使用import '模块名'的形式来进行模块的调用。
  • 当我们需要导入模块之中所有的值的时候,可以使用*号表示。代码如下:
    import * from './profile.js'
  • 当export之中使用了default进行导出的时候,我们可以不是用结构赋值的形式,而是直接的用自定义的名称还导出相关的模块数据。例如:
    export default function(){
        ...
    }

    import checkAPI from "./xxx.js"

8. export

  • 相对应于import我们也有导出使用的export内容。我们可以直接在模块之中声明的变量前使用export来说明当前的变量或者方法是需要导出的,或者我们可以同意的通过{变量名,方法名}的形式来进行内容的导出。
  • 当我们导出相关变量和方法的时候,其对应的名称就是我们导出的变量的名称,或者想要叫别的名称的时候,可以通过使用as关键字来进行名称的修改。看一段代码:
    function v1() { ... }
    function v2() { ... }
    
    export {
      v1 as streamV1,
      v2 as streamV2,
      v2 as streamLatestVersion
    };
  • export之中有一个default关键字,表示默认导出内容,default其实就可以看成当前导出数据的名称,只不过它是一个关键字而已,所以才会导致下面看起来有些奇异的使用方式:
    export default function crc32() { // 输出
      // ...
    }
    
    export default 42;
    上面两种用法都是成立的。
  • 当然default也是可以用作别名的,或者单单表示默认输出代码段而已,代码如下:
    var a = 1;
    export default a;
    
    function add(x, y) {
      return x * y;
    }
    export {add as default};
  • export有一种和import的符合用法 形如:export {a, b} from "./xxx.js"这种形式,表明的是先将a和b从xxx.js之中引入,在exoprt导出。但是这里有一点要注意的是,这种结合形式所书写的模块是无法使用a和b接口的。这种方式常常用于模块的继承编写。当然这种写法之中的接口名称也是可以通过as来设置别名的。

结束

上面介绍的都是声明使用的ES6新关键字(不论是声明变量,类还是模块)了,以及相关性较强的一部分,在此处介绍了,之后可能还是会有新的关键字出现,那些将会在介绍相关的ES6概念的时候来一同说明。本篇文章就到这吧,让我们共同学习,共同成长。