zoukankan      html  css  js  c++  java
  • ES6——class类继承(读书笔记)

    前言

      我一定是一个傻子,昨天这篇文章其实我已经写好了一半了,但是我没有保存

      这是学习ES6的过程,我没有系统的看完阮大大的书。零零散散的,很多功能知道,但是没有实际的用过

      看了几遍,总是看前面几章,所以这次我要立下flag 一定从头到尾学一遍ES6(有点讽刺 现在好像都有ES9了)

      ES5与ES6 相差还是很大的

    一、类

      ES5 没有类这个说法,但是是可以实现类这样功能的,那就是构造函数 

    function Point (x,y){
      this.x = x
      this.y = y    
    }
    
    var a  = new Point(1,2)
    console.log(a.x) //1

      然后我在mdn上找到一个例子 详细的说了构造函数的原型 原型链

      

    // 让我们从一个自身拥有属性a和b的函数里创建一个对象o:
    let f = function () {
       this.a = 1;
       this.b = 2;
    }
    /* 这么写也一样
    function f() {
      this.a = 1;
      this.b = 2;
    }
    */
    let o = new f(); // {a: 1, b: 2}
    
    // 在f函数的原型上定义属性
    f.prototype.b = 3;
    f.prototype.c = 4;
    
    // 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
    // o.[[Prototype]] 有属性 b 和 c
    //  (其实就是 o.__proto__ 或者 o.constructor.prototype)
    // o.[[Prototype]].[[Prototype]] 是 Object.prototype.
    // 最后o.[[Prototype]].[[Prototype]].[[Prototype]]是null
    // 这就是原型链的末尾,即 null,
    // 根据定义,null 就是没有 [[Prototype]]。
    
    // 综上,整个原型链如下: 
    
    // {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null
    
    console.log(o.a); // 1
    // a是o的自身属性吗?是的,该属性的值为 1
    
    console.log(o.b); // 2
    // b是o的自身属性吗?是的,该属性的值为 2
    // 原型上也有一个'b'属性,但是它不会被访问到。
    // 这种情况被称为"属性遮蔽 (property shadowing)"
    
    console.log(o.c); // 4
    // c是o的自身属性吗?不是,那看看它的原型上有没有
    // c是o.[[Prototype]]的属性吗?是的,该属性的值为 4
    
    console.log(o.d); // undefined
    // d 是 o 的自身属性吗?不是,那看看它的原型上有没有
    // d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有
    // o.[[Prototype]].[[Prototype]] 为 null,停止搜索
    // 找不到 d 属性,返回 undefined

      看完这个例子,就大概知道原型 原型链 是怎样一层一层的找的(又有灵感 写一篇古风版的原型链了)

      然后ES6 是怎么样的呢

    class Point{
            constructor(x,y){
                this.x = x;
                this.y = y;
          }
        toString(){
            return "("+this.x+","+this.y+")"
        }
    }           

     上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法 

       而this关键字则代表实例对象。也就是说,ES5 的构造函数Point,对应 ES6 的Point类的构造方法。

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

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

     类的所有方法都定义在类的prototype属性上面。(继承) 在类的实例上面调用方法,其实就是调用原型上的方法。

    class B {}
    let b = new B();
    
    b.constructor === B.prototype.constructor // true

      prototype对象的constructor属性,直接指向“类”的本身,这与 ES5 的行为是一致的。

     Point.prototype.constructor === Point // true

    toString方法是Point类内部定义的方法,它是不可枚举的。这一点与 ES5 的行为不一致。

    constructor方法

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

    class Point {
    }
    
    // 等同于
    class Point {
      constructor() {}
    }
    1. 类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行
    2. constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例。
    3. class Foo {
        constructor() {
          return Object.create(null);
        }
      }
      
      new Foo() instanceof Foo
      // false
    4. 类不存在变量提升(hoist),这一点与 ES5 完全不同。
    5. {
        let Foo = class {};
        class Bar extends Foo {
        }
      }

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

    6. 由于本质上,ES6 的类只是 ES5 的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性  name属性总是返回紧跟在class关键字后面的类名。
      class Point {}
      Point.name // "Point"
    7. 如果某个方法之前加上星号(*),就表示该方法是一个 Generator 函数。
    8. class Foo {
        constructor(...args) {
          this.args = args;
        }
        * [Symbol.iterator]() {
          for (let arg of this.args) {
            yield arg;
          }
        }
      }
      
      for (let x of new Foo('hello', 'world')) {
        console.log(x);
      }
      // hello
      // world

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

    9. 在构造方法中绑定this,这样就不会找不到print方法了。 不然就会this会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined),从而导致找不到print方法而报错。
    10. 另一种解决方法是使用箭头函数。
    11. class Obj {
        constructor() {
          this.getThis = () => this;
        }
      }
      
      const myObj = new Obj();
      myObj.getThis() === myObj // true

    二、静态方法

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

      

    class Foo {
      static classMethod() {
        return 'hello';
      }
    }
    
    Foo.classMethod() // 'hello'
    
    var foo = new Foo();
    foo.classMethod()
    // TypeError: foo.classMethod is not a function

      

  • 相关阅读:
    HDU 1813 Escape from Tetris
    BZOJ 2276 Temperature
    BZOJ 4499 线性函数
    BZOJ 3131 淘金
    HDU 5738 Eureka
    POJ 2409 Let it Bead
    POJ 1286 Necklace of Beads
    POJ 1696 Space Ant
    Fox And Jumping
    Recover the String
  • 原文地址:https://www.cnblogs.com/ifannie/p/11091532.html
Copyright © 2011-2022 走看看