lizhongzhen11 / lizz-blog

前端学习
80 stars 6 forks source link

重学js —— 类定义(class) #88

Open lizhongzhen11 opened 4 years ago

lizhongzhen11 commented 4 years ago

类定义(class)

class定义始终是 严格模式代码

// 有意思,直接空语句也行
class ClassTest{
  ;
  test;
}

BoundNames

ClassDeclaration : class BindingIdentifier ClassTail

  1. 返回 BindingIdentifier 的 BoundNames

ClassDeclaration : class ClassTail

  1. 返回 « "*default*" »

ConstructorMethod (构造器方法)

ClassElementList : ClassElement

class Test{
  constructor() {
    // ...  
  }
}
  1. 如果 ClassElementClassElement : ; ,返回 empty
  2. 如果 ClassElement静态的,返回 empty
  3. 如果 ClassElement 的属性名不是 "constructor",返回 empty
  4. 返回 ClassElement

ClassElementList : ClassElementList ClassElement

class Test{
  constructor() {
    // ...  
  }
  handle() {
    // ...  
  }
}
  1. 定义 headClassElementListConstructorMethod
  2. 如果 head 不是 empty,返回 head
  3. 如果 ClassElementClassElement : ; ,返回 empty
  4. 如果 ClassElement静态的,返回 empty
  5. 如果 ClassElement 的属性名不是 "constructor",返回 empty
  6. 返回 ClassElement

IsFunctionDefinition (是不是函数)

class Cla{}
typeof Cla // 'function'
  1. 返回 true

NonConstructorMethodDefinitions (非构造器方法定义)

ClassElementList : ClassElement

  1. 如果 ClassElementClassElement : ;,返回一个新的空 List
  2. 如果 ClassElement 不是静态的,并且 ClassElement 的属性名是 "constructor",返回一个新的空 List
  3. 返回一个包含 ClassElementList

ClassElementList : ClassElementList ClassElement

  1. 定义 listClassElementListNonConstructorMethodDefinitions
  2. 如果 ClassElementClassElement : ;,返回 list
  3. 如果 ClassElement 不是静态的,并且 ClassElement 的属性名是 "constructor",返回 list
  4. list 末尾添加 ClassElement
  5. 返回 list

ClassDefinitionEvaluation

伴有参数 classBindingclassName

ClassTail : ClassHeritageopt { ClassBodyopt }

  1. 定义 lex运行时执行上下文LexicalEnvironment
  2. 定义 classScopeNewDeclarativeEnvironment(lex)
  3. 定义 classScopeEnvRecclassScopeEnvironmentRecord
  4. 如果 classBinding 不是 undefined
    1. 执行 classScopeEnvRec.CreateImmutableBinding(classBinding, true)
  5. 如果 ClassHeritageopt 不存在,
    1. 定义 protoParent%Object.prototype%
    2. 定义 constructorParent%Function.prototype%
  6. 否则,
    1. 运行时执行上下文LexicalEnvironment 设置为 classScope
    2. 定义 superclassRefClassHeritage 求值结果
    3. 运行时执行上下文LexicalEnvironment 设置为 lex
    4. 定义 superclass? GetValue(superclassRef)
    5. 如果 superclassnull
      1. 定义 protoParentnull
      2. 定义 constructorParent%Function.prototype%
    6. 如果 superclass 不是构造器,抛 TypeError 异常
    7. 否则,
      1. 定义 protoParent? GetValue(superclass, "prototype")
      2. 如果 protoParent 既不是对象类型又不是 Null 类型,抛 TypeError 异常
      3. 定义 constructorParentsuperclass
  7. 定义 protoOrdinaryObjectCreate(protoParent)
  8. 如果 ClassBodyopt 不存在,定义 constructorempty
  9. 否则,定义 constructorClassBodyConstructorMethod
  10. 如果 constructorempty
    1. 如果 ClassHeritageopt 存在,
      1. constructor 赋值为 源文本 的解析结果
        constructor(...args) { super(...args); }

        将语法与 目标符号 MethodDefinition[~Yield, ~Await] 一起使用

    2. 否则,
      1. constructor 赋值为 源文本 的解析结果
        constructor() { }

        将语法与 目标符号 MethodDefinition[~Yield, ~Await] 一起使用

  11. 运行时执行上下文LexicalEnvironment 设置为 classScope
  12. 定义 constructorInfoconstructor! DefineMethod,且参数为 protoconstructorParent
  13. 定义 FconstructorInfo.[[Closure]]
  14. 执行 MakeConstructor(F, false, proto)
  15. 如果 ClassHeritageopt 存在,将 F.[[ConstructorKind]] 赋值为 derived
  16. 执行 MakeClassConstructor(F)
  17. 如果 className 不是 undefined
    1. 执行 SetFunctionName(F, className)
  18. 执行 CreateMethodProperty(proto, "constructor", F)
  19. 如果 ClassBodyopt 不存在,定义 methods 为 一个新的空 List
  20. 否则,定义 methodsClassBodyNonConstructorMethodDefinitions
  21. 遍历 methods 中的每个 ClassElement m
    1. 如果 m 不是静态的,
      1. 定义 statusmPropertyDefinitionEvaluation,且参数为 protofalse
    2. 否则,
      1. 定义 statusmPropertyDefinitionEvaluation,且参数为 Ffalse
    3. 如果 statusabrupt completion
      1. 运行时执行上下文LexicalEnvironment 设置为 lex
      2. 返回 (status)
  22. 运行时执行上下文LexicalEnvironment 设置为 lex
  23. 如果 classBinding 不是 undefined
    1. 执行 classScopeEnvRec.InitializeBinding(classBinding, F)
  24. 返回 F

BindingClassDeclarationEvaluation

ClassDeclaration : class BindingIdentifier ClassTail

  1. 定义 classNameBindingIdentifier 的字符串值
  2. 定义 valueClassTail? ClassDefinitionEvaluation,且参数为 classNameclassName
  3. value.[[SourceText]] 设置为与 ClassDeclaration 匹配的 源文本
  4. 定义 env运行时执行上下文LexicalEnvironment
  5. 执行 ? InitializeBoundName(classBinding, value, env)
  6. 返回 value

ClassDeclaration : class ClassTail

  1. 定义 valueClassTail? ClassDefinitionEvaluation,且参数为 undefined"default"
  2. value.[[SourceText]] 设置为与 ClassDeclaration 匹配的 源文本
  3. 返回 value

求值

ClassDeclaration : class BindingIdentifier ClassTail

  1. 执行该 ClassDeclaration? BindingClassDeclarationEvaluation
  2. 返回 (empty)

注意:ClassDeclaration : class ClassTail 仅作为 ExportDeclaration 的一部分出现并且从不直接求值。

ClassExpression : class BindingIdentifieropt ClassTail

  1. 如果 BindingIdentifieropt 不存在,定义 classNameundefined
  2. 否则,定义 classNameBindingIdentifier 的字符串值
  3. 定义 valueClassTail? ClassDefinitionEvaluation,且参数为 classNameclassName
  4. value.[[SourceText]] 设置为与 ClassExpression 匹配的 源文本
  5. 返回 value
// 静态方法
// static 关键字用来定义一个类的一个静态方法。
// 调用静态方法不需要实例化该类,但不能通过一个类实例调用静态方法。
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  static distance(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;
    return Math.hypot(dx, dy);
  }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.distance(p1, p2));
console.log(p1.distance); // undefined

// 公有字段 与 私有字段
class Rectangle {
  height = 0; // 公有字段
  #width; // 私有字段
  constructor(height, width) {    
    this.height = height;
    this.#width = width;
  }
}

// 来自高级前端面试,我做错了
class Chameleon{
  static colorChange(newColor) {
    this.newColor = newColor;
  }

  constructor({newColor = 'green'}) {
    this.newColor = newColor;
  }
}
const freddie = new Chameleon({newColor: 'purple'})
freddie.colorChange('orange') // 选D

A. orange
B. purple
C. green
D. TypeError

// 同理,下面也是报错
class test extends Chameleon{
  constructor() {
    super({newColor: 'purple'})
    super.colorChange('red')
  }
}
new test // TypeError