• es6的class关键字与es5的构造函数


    1,构造函数

    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    
    Point.prototype.toString = function () {
      return '(' + this.x + ', ' + this.y + ')';
    };
    
    var p = new Point(1, 2);
    
    console.log(p)
    console.log(p.toString)
    
    效果等同于
    
    function Point(x, y) {
      this.x = x;
      this.y = y;
      this.toString = function () {
         return '(' + this.x + ', ' + this.y + ')';
      };
    }
    
    var p = new Point(1, 2);
    
    console.log(p)
    console.log(p.toString)
    
    但是意义不一样,前者定义在生成对象的原型中;
    后者直接定义在属性中

    结果:

    可见:

    1、构造函数也是一个普通函数,创建方式和普通函数一样,但构造函数习惯上首字母大写
    
    2、构造函数和普通函数的区别在于:调用方式不一样。作用也不一样(构造函数用来新建实例对象)
    
    3、调用方式不一样。
        a. 普通函数的调用方式:直接调用 person();
        b.构造函数的调用方式:需要使用new关键字来调用 new Person();
    
    4、构造函数的函数名与类名相同:Person( ) 这个构造函数,Person 既是函数名,也是这个对象的类名
    
    5、内部用this 来构造属性和方法 

    2,class:

    ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。下面的代码等同于以上es5的第一种写法。

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

    上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Point,对应 ES6 的Point类的构造方法。

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

    ES6 的类,完全可以看作构造函数的另一种写法。

    class Point {
      // ...
    }
    
    typeof Point // "function"
    Point === Point.prototype.constructor // true

    上面代码表明,类的数据类型就是函数,类本身就指向构造函数。

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

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

    构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。

    class Point {
      constructor() {
        // ...
      }
    
      toString() {
        // ...
      }
    
      toValue() {
        // ...
      }
    }
    
    // 等同于
    
    Point.prototype = {
      constructor() {},
      toString() {},
      toValue() {},
    };

    在类的实例上面调用方法,其实就是调用原型上的方法。

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

    上面代码中,bB类的实例,它的constructor方法就是B类原型的constructor方法。

    2.1 Object.assign添加class方法

    由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign方法可以很方便地一次向类添加多个方法。

    class Point {
      constructor(){
        // ...
      }
    }
    
    Object.assign(Point.prototype, {
      toString(){},
      toValue(){}
    });

    2.2静态方法:static

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

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

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

    注意,如果静态方法包含this关键字,这个this指的是类,而不是实例。

    (类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。

    解决方案:1,在构造方法中绑定this;2,使用箭头函数;3,使用Proxy)

    class Foo {
      static bar() {
        this.baz();
      }
      static baz() {
        console.log('hello');
      }
      baz() {
        console.log('world');
      }
    }
    
    Foo.bar() // hello

    上面代码中,静态方法bar调用了this.baz,这里的this指的是Foo类,而不是Foo的实例,等同于调用Foo.baz。另外,从这个例子还可以看出,静态方法可以与非静态方法重名。

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

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

    2.3实例属性的新写法

    2.4静态属性

    2.5私有方法和私有属性

    2.6new.target 属性

    引用自 http://es6.ruanyifeng.com/#docs/class

    可参考另一篇博文:https://www.cnblogs.com/wangtong111/p/11242557.html

  • 相关阅读:
    Pieczęć(模拟)
    【并查集】关押罪犯
    火车进栈
    独木舟上的旅行
    哈尔滨理工大学第八届程序设计团队赛K题
    [数学、递推]Everything Is Generated In Equal Probability
    [构造]triples I
    2019牛客第三场
    [DP]销售
    [哈夫曼树]猜球球
  • 原文地址:https://www.cnblogs.com/wangtong111/p/11326412.html
Copyright © 2020-2023  润新知