Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Note:JavaScript面对象系统之构造器 #7

Open
XiaoDHuang opened this issue Dec 24, 2019 · 1 comment
Open

Note:JavaScript面对象系统之构造器 #7

XiaoDHuang opened this issue Dec 24, 2019 · 1 comment
Labels
documentation Improvements or additions to documentation

Comments

@XiaoDHuang
Copy link
Owner

No description provided.

@XiaoDHuang XiaoDHuang changed the title Note:JavaScript面对象系统之构造器 Note:JavaScript面对象系统之构造器??? Dec 24, 2019
@XiaoDHuang
Copy link
Owner Author

XiaoDHuang commented Dec 25, 2019

JavaScript构造器

概述作用

  • 是JavaScript 中面向对象系统的核心概念之一
  • 动态构建静态属性列表结构的逻辑

类与构造器

在 ECMAScript 6 之后,函数可以简单地分为三个大类:

  • 类 (只可以做 new 运算;)
  • 一般函数:(除部分函数有特殊限制外,)同时可以做 new 和调用运算。
  • 方法:只可以做调用“( )”运算

在 ECMAScript 6 方法特性

  • 具有一个名为“主对象[[HomeObject]]”的内部槽;
  • 没有名为“构造器[[Construct]]”的内部槽;
  • 没有名为“prototype”的属性

总结

  • 如果没有[[Construct]]内部槽和prototype属性, 可以排除一个普通方法作为构造器的可能性
  • 类作为方法来创建,有独立的构建过程,和原型属性。
  • 函数的“.prototype”的属性描述符中的设置比较特殊,它不能删除,但可以修改
    • prototype 为 null , 子类以null为原型
    • prototype 非对象值时, 子类以Object.prototype 为原型
    • prototype 为对象时, 子类以该对象为原型

【ECMAScript 6】 this创建顺序

  • 【问题1 ES6之前】无法创建一个有特殊性质的对象,也无法声明一个具有这类特殊性质的类。
f = new Function;

f instanceof Function  // true

f() //undefined
MyFunction = function() {};
MyFunction.prototype = new Function;
f = new MyFunction;
[f instanceof MyFunction, f instanceof Functcion]
// [ true, true ]

f() //TypeError: f is not a funct

JavaScript 所谓的函数,其实是“一个有[[Call]]内部槽的对象”。而Function()作为 JavaScript 原生的函数构造器,它能够在创建的对象(例如this)中添加这个内部槽,而当使用上面的继承逻辑时,用户代码(例如MyFunction())就只是创建了一个普通的对象,因为用户代码没有能力操作 JavaScript 引擎层面才支持的那些“内部槽”。
有一些“类 / 构造器”在 ECMAScript 6 之前是不能派生子类的,例如 Function,又例如 Date。

ECMAScript 6 的类是由父类或祖先类创建this实例的。

它的“类声明”采用了不同的构造逻辑。ECMAScript 6 要求所有子类的构造过程都不得创建这个this实例,并主动的把这个创建的权力“交还”给父类、乃至祖先类。这也就是 ECMAScript 6 中类的两个著名特性的由来,即,如果类声明中通过 extends 指定了父类,那么:

  • 必须在构造器方法(constructor)中显式地使用super()来调用父类的构造过程
  • 在上述调用结束之前,是不能使用this引用的。
class MyFunction extends Function { }

f = new MyFunction;

f() //undefined

用户返回 new 结果规则

  • 用户代码可以干涉 new 运算的结果值
    • 当构造器返回无效值(非对象值或 null) 用已经创建的this对象来替代返回的无效值
    • 派生的子类(即声明中使用了extends子句的类) 不得在构造器中返回非对象值(以及 null 值)并在这种情况下直接抛出异常。
## (注:ES3之前将抛出异常)
new (function() {return 1}); // {}

## 非派生类的构造方法返回无效值
new (class { constructor() { return 1 } }) //{}

## 派生类的构造方法返回无效值
new (class extends Object { constructor() { return 1 } })  // TypeError: Derived constructors may only return object or undefined

知识总结

  • 在使用类声明来创建对象时,对象是由父类或祖先类创建的实例,并使用this引用传递到当前(子级的)类的。
  • 在类的构造方法和一般构造器(函数)中返回值,是可以影响 new 运算的结果的,但 JavaScript 确保 new 运算不会得到一个非对象值。
  • 类或构造器(函数)的首字母大写是一种惯例,而不是语言规范层面的约束。
  • 类继承过程也依赖内部构造过程([[Contruct]])和原型属性(prototype),并且类继承实际上是原型继承的应用与扩展,不同于早期 JavaScript1.0 使用的类抄写。

推荐&打赏

  • 如果您觉得还不错,可以到极客时间订阅,顺便我可以获取您订阅后的优惠券

@XiaoDHuang XiaoDHuang added the documentation Improvements or additions to documentation label Dec 25, 2019
@XiaoDHuang XiaoDHuang changed the title Note:JavaScript面对象系统之构造器??? Note:JavaScript面对象系统之构造器 Dec 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant