ES6几点知识

本篇文章记录的是ES6中的letclassextendsuper,这几个与react编写过程遇到的知识
参考:阮一峰ES6

let命令

它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。例如在for循环就适合用let
ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。

    {
        let a = 10;
        var b = 1;
  }
  a // ReferenceError: a is not defined.
  b // 1

严格模式主要有以下限制。

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀0表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • eval和arguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象
  • 不能使用fn.caller和fn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protected、static和interface)

不存在变量提升

var命令会发生变量提升现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错

    console.log(foo); // 输出undefined
    var foo = 2;

    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
暂时性死区

ES6明确规定,如果区块中存在 letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

    var tmp = 0;
    if(true) {
        tmp = 2;
        let tmp;
    }
Paste_Image.png
    tmp = 0;
Paste_Image.png

在没有let之前,typeof运算符是百分之百安全的,永远不会报错。现在这一点不成立了。这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

class的基本用法

在ES5中,大部分是通过构造函数的形式来定义类。
在es6中,新添加一种通过class构造类的方法。

    class Point {
      constructor(x, y) {
          this.x = x;
          this.y = y;
        }

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

在上述定义中,constructor就是构造方法,相当与构造函数,this就是构造的实例对象
Point类除了构造方法,还定义了一个toString方法。

注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。
另外,方法之间不需要逗号分隔,加了会报错。

使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。

class Point {
    constructor(props) {
        this.x = x;
        this.y = y;
    }

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

var m = new Point(x = 2, y = 4);
console.log(m.toString());
  //(2, 4)
在类的实例上面调用方法,其实就是调用原型上的方法。
  class B {}
  let b = new B();
  b.constructor === B.prototype.constructor

在这个例子中,bB的实例,B.prototype是原型,
由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign方法可以很方便地一次向类添加多个方法

       class Point {
    constructor(x, y) {
      this.x = x;
      this.y = y;
    }
  }
  Object.assign(Point.prototype, {
    toValue() {},
    toString() {}
  });

prototype对象的constructor属性,直接指向“类”的本身

  console.log(Point === Point.prototype.constructor);  //true
类的内部所有定义的方法,都是不可枚举的(non-enumerable)
class Point {
    constructor(x, y) {
      this.x = x;
      this.y = y;
    }

     toString() {}         
  }

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

 class Point {
    constructor(x, y) {
      return Object.create(null);
    }

     toString() {}

  }
  
  var m = new Point();
  console.log(m instanceof Point);

该例子显示定义了constructor返回的创建一个空对象,所以输出为false

类的构造函数,不使用new是没法调用的,会报错

class Point {
    constructor(x, y) {
      return Object.create(null);
    }

     toString() {}

  }
  
  var m = Point();
Paste_Image.png

与ES5一样,实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上,就是说实例输入的值是其本身属性,其他均为原型属性

  class Point {
    constructor(x, y) {
      this.x = x;
      this.y = y;
    }

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

  }
  
  var m = new Point(1,2);
  console.log(m.hasOwnProperty('x'));    //true
  console.log(m.hasOwnProperty('y'));    //true
  console.log(m.hasOwnProperty('toString'));      //false
  console.log(m.__proto__.hasOwnProperty('toString'));  //true,记住了原型是这样的

可以通过实例的__proto__属性为Class添加方法

var m = new Point(1,2);
  var n = new Point(2,8)

  m.__proto__.playTime = function () {
    return this.x + this.y + ' minutes';
  }
  console.log(m.playTime()); 
  console.log(n.playTime());
Paste_Image.png
这意味着,使用实例的proto属性改写原型,必须相当谨慎,不推荐使用,因为这会改变Class的原始定义,影响到所有实例。

Class不存在变量提升(hoist),这一点与ES5完全不同。要先定义后使用,否则报错。
因为ES6不会把类的声明提升到代码头部。

    {
        let Foo = class {};
        class Bar extends Foo {
            }
    }

上面的代码不会报错,因为Bar继承Foo的时候,Foo已经有定义了。但是,如果存在class的提升,上面代码就会报错,因为class会被提升到代码头部,而let命令是不提升的,所以导致Bar继承Foo的时候,Foo还没有定义。

Class表达式

类的名字是MyClass,Me只在内部有定义,所以Me是可以省略的

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

  let inst = new MyClass();
  console.log(inst.getClassName());   
  console.log(Me.name);
Paste_Image.png

this的指向

类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。
一个比较简单的解决方法是,在构造方法中绑定this,这样就不会找不到print方法了

class Logger {
    constructor() {
    this.printName = this.printName.bind(this);
      }

      // ...
  }

另一种解决方法是使用箭头函数

class的继承

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

    class ColorPoint extends Point {}

    class ColorPoint extends Point {
            constructor(x, y, color) {
            super(x, y); // 调用父类的constructor(x, y)
            this.color = color;
      }

    toString() {
        return this.color + ' ' + super.toString(); // 调用父类的toString()
      }
  }

super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。

子类必须constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

如果子类没有定义constructor方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor方法。

    constructor(...args) {
            super(...args);
        }

另一个需要注意的地方是,在子类的构造函数中,只有调用 super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

    class Point {
        constructor(x, y) {
                this.x = x;
                this.y = y;
            }
    }

    class ColorPoint extends Point {
            constructor(x, y, color) {
            this.color = color; // ReferenceError
            super(x, y);
            this.color = color; // 正确
        }
    }

super

super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

  • 第一种情况,super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。

        class A {}
    
        class B extends A {
              constructor() {
              super();
          }
      }
    

上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。

  • 第二种情况,super作为对象时,指向父类的原型对象
    这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的
    不过,如果属性定义在父类的原型对象上,super就可以取到
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容

  • class的基本用法 概述 JavaScript语言的传统方法是通过构造函数,定义并生成新对象。下面是一个例子: ...
    呼呼哥阅读 4,091评论 3 11
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,801评论 1 10
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,649评论 0 11
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,622评论 18 399
  • 不管生活给予我们什么 努力做自信、善良 坚强、有骨气的女子
    朕略萌0701阅读 233评论 0 0