zoukankan      html  css  js  c++  java
  • 读书笔记:深入理解ES6 (九)

    第九章 JavaScript中的类

    第1节 ES5中的近类结构

      ES5及早期版本中没有类的概念,因此用了一个相近的思路来创建一个自定义类型:首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型。例如:

     1 function PersonType(name)
     2 {
     3     this.name = name;
     4 }
     5 
     6 PersonType.prototype.sayName = function() {
     7     console.log(this.name);
     8 }
     9 
    10 var person = new PersonType("zxx");
    11 person.sayName(); // "zxx"
    12 
    13 console.log(person instanceof PersonType); //true
    14 console.log(person instanceof Object); //true

    第2节 类的声明

      1. 在ES6中,要声明一个类,先写 class 关键字,然后是类的关键字。例如:

     1 class PersonClass {
     2     //等价于PersonType构造函数
     3     constructor(name) {
     4         this.name = name;
     5     }
     6 
     7     //等价于PersonType.prototype.sayName
     8     sayName() {
     9         console.log(this.name);
    10     }
    11 }
    12 
    13 let person = new PersonClass("zxx");
    14 person.sayName(); //"zxx"
    15 
    16 console.log(person instanceof PersonClass); //true
    17 console.log(person instanceof Object); //true
    18 console.log( typeof PersonClass); //"function"
    19 console.log( typeof PersonClass.prototype.sayName); //"function"

      2. 自有属性

      自有属性是实例中的属性,不会出现在原型上,只能在类的构造函数或方法中创建,此例中的 name 就是一个自有属性。

      3. 类与自定义类型的差异:

        1)函数声明可以被提升,而类声明与 let 类似,不能被提升;

        2)类声明中的所有代码将运行在严格模式下;

        3)在类中,所有方法都是不可枚举的;

        4)每个类中,都有一个名为 [[Construct]] 的内部方法,通过关键字new调用那些不含 [[Construct]] 的方法回导致程序抛出错误;

        5)使用除 new 以外的方式调用类的构造函数会导致程序抛出错误;

        6)在类中,修改类名会导致程序报错。

    第3节 类表达式

      类和函数都有两种存在形式:声明形式和表达形式。声明形式的函数和类都由相应关键字(分别为function,class)进行定义,随后紧跟一个标识符。表达形式的函数和类与之类似,只是不需要再关键字后加标识符。举例:

     1 let PersonClass = class {
     2     //等价于PersonType构造函数
     3     constructor(name) {
     4         this.name = name;
     5     }
     6 
     7     //等价于PersonType.prototype.sayName
     8     sayName() {
     9         console.log(this.name);
    10     }
    11 }
    12 
    13 let person = new PersonClass("zxx");
    14 person.sayName(); //"zxx"
    15 
    16 console.log(person instanceof PersonClass); //true
    17 console.log(person instanceof Object); //true
    18 console.log( typeof PersonClass); //"function"
    19 console.log( typeof PersonClass.prototype.sayName); //"function"

    第4节 作为一等公民的类

      1. 什么是一等公民?

        一等公民是指一个可以传入函数,可以从函数返回,并且可以赋值给变量的值。

      2. JavaScript中函数、类都是一等公民

    第5节 访问器属性

      尽管应该在类构造函数中创建自己的属性,但类也支持直接在原型上定义访问器属性。创建 getter 时,需要在关键字 get 后紧跟一个空格和相应的标识符;创建 setter 时,只需要把 getter 关键字 get 替换为set即可。

    第6节 可计算成员名称

      1. 类方法和访问器属性也支持使用可计算名称。用方括号包裹一个表达式,即可使用可计算名称。例如:

     1 let methodName = "sayName";
     2 
     3 class PersonClass {
     4     constructor(name) {
     5         this.name = name;
     6     }
     7 
     8     [methodName]() {
     9         console.log(this.name);
    10     }
    11 };
    12 
    13 let me = new PersonClass("zxx");
    14 me.sayName(); // "zxx"

      2. 同样地,在访问器属性中也可以使用可计算名称。例如:

     1 let propertyName = "html";
     2 
     3 class CustomHTMLElement {
     4     constructor(element) {
     5         this.element = element;
     6     }
     7 
     8     get [propertyName]() {
     9         return this.element.innerHTML;
    10     }
    11 
    12     set [propertyName]() {
    13         this.element.innerHTML = value;
    14     }
    15 }

    第7节 生成器方法

      在类中,也可以通过 “*” 来定义生成器。如果类是用来表示值的集合的,那么为它定义一个默认迭代器会更有用。

    第8节 静态成员

      ES5、ES6中都有静态成员的语法。下面分别讲一下它们:

      1. ES5中,通过直接将方法添加到构造函数中类模拟静态成员。例如:

     1 function PersonType(name) {
     2     this.name = name;
     3 }
     4 
     5 //静态方法
     6 PersonType.create = function(name) {
     7     return new PersonType(name);
     8 };
     9 
    10 //实例方法
    11 PersonType.prototype.sayName = function() {
    12     console.log(this.name);
    13 };
    14 
    15 var person = PersonType.create("zxx");

      2. 在ES6中,简化了创建静态成员的语法。在方法或者访问器属性名前使用正式的静态注释(static)即可。例如:

     1 class PersonClass {
     2     //等价于PersonType的构造函数
     3     constructor(name) {
     4         this.name = name;
     5     }
     6 
     7     //等价于PerosonType.prototype.sayName
     8     sayName() {
     9         console.log(this.name);
    10     }
    11     
    12     //等价于PersonType.create()
    13     static create(name) {
    14         return new PersonClass(name);
    15     }
    16 }
    17 
    18 let person = PersonClass.create("zxx");

      3. 注意:

        1)类中的所有方法和访问器属性都可以用static关键字类定义,唯一的限制是不能将static用于定义构造函数方法。

        2)不可在实例中访问静态成员,必须要直接在类中访问静态成员。

    第9节 继承与派生类

      1. 基本概念介绍

        1)使用 extends 关键字可以指定类继承的函数。

        2)通过 super() 方法即可访问基类的构造函数。

        3)继承自其它类的类被称作派生类。

        4)如果不使用构造函数,则当创建新的类实例时会自动调用 super() 并传入所有参数。

        5)使用super()需要注意:

          a. 只可以在派生类的构造函数中使用super()

          b. 在构造函数中,访问 this 之前一定要调用 super(),它负责初始化this

          c. 如果不想调用 super(),唯一的方法是让类的构造函数返回一个对象。

      2. 类方法遮蔽

        派生类中的方法总会覆盖基类中的同名方法。如果仍然想使用基类中的方法,则可以借助 super 关键字来实现。

      3. 静态成员继承

        派生类继承基类后,基类中的静态成员也可以直接在派生类中使用。

      4. 派生自表达式的类

        1)只要表达式可以被解析为一个函数,并且具有[[Construct]]属性和原型,那么就可以用extends进行派生。

        2)extends强大的功能使得类可以继承自任意类型的表达式,而且可以是不止一个的表达式,这样可以动态地确定类的继承目标,创建不同的继承方法。举例:

     1 function Rectangle(length, width)
     2 {
     3     this.length = length;
     4     this.width = width;
     5 }
     6 
     7 Rectangle.prototype.getArea = function() {
     8     return this.length * this.width;
     9 }
    10 
    11 function getBase()
    12 {
    13     return Rectangle;
    14 }
    15 
    16 class Square extends getBase() {
    17     constructor(length) {
    18         super(length * length);
    19     }
    20 }
    21 
    22 var x = new Square(3);
    23 
    24 console.log(x.getArea()); //9
    25 console.log(x instanceof Rectangle); //true

      5. 内建对象的继承。

        在ES5中,无法通过继承的方式创建属于自己的特殊数组。而ES6类语法的一个目标是支持内建对象的继承。具体是:先由基类(Array)创建this的值,然后派生类的构造函数(MyArray)再修改这个值。举例:

     1 class MyArray extends Array {
     2     //
     3 }
     4 
     5 var colors = new MyArray();
     6 colors[0] = "red";
     7 
     8 console.log(colors.length); //1
     9 
    10 colors.length = 0;
    11 console.log(colors[0]) // undefined

      6. Symbol.species属性

        内建对象继承的一个实用之处是,原本在内建对象中返回实例自身的方法将自动返回派生类的实例。

        通过Symbol.species可以定义当派生类的方法返回实例时,应该返回的值的类型。

    第10节 在类的构造函数中使用new.target

      类的构造函数必须通过new关键字调用,所以总是在类的构造函数中定义new.target属性。但是其值有时会不同。每个构造函数都可以根据自身被调用的方式改变自己的行为。例如,可以用new.target创建一个抽象基类(不能被直接实例化的类),就像这样:

     1 //抽象基类
     2 class Shape {
     3     constructor() {
     4         if (new.target === Shape) {
     5             throw new Error("这个类不能被直接实例化");
     6         }
     7     }
     8 }
     9 
    10 class Rectangle extends Shape {
    11     constructor(length, width) {
    12         super();
    13         this.length = length;
    14         this.width = width;
    15     }
    16 }
    17 
    18 var x = new Shape(); // 抛出错误
    19 
    20 var y = new Rectangle(3,4); //没有错误
    21 console.log(y instanceof Shape); // true

    (本节完)

  • 相关阅读:
    Linux系统中常用操作命令
    CentOS 7 巨大变动之 systemd 取代 SysV的Init
    不可不知的安卓屏幕知识
    Gradle-jar-aar
    【Android】开源项目汇总
    Android中关于系统Dialog无法全屏的问题(dialog样式)
    Android LockScreen (锁屏弹窗)
    linux 权限设置
    android 多语言(在APP里面内切换语言)
    host更新
  • 原文地址:https://www.cnblogs.com/zxxsteven/p/11510945.html
Copyright © 2011-2022 走看看