js 基础 - class
2023-07-25 18:15:47
# fontend
1. new 操作符干了什么?
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
- 创建一个新对象
- 新对象的原型对象指向当前构造函数的原型对象
- 当前 this 指针指向新对象
- 如果没有返回对象,则返回 this
1 | function _new(obj, ...rest) { |
2. new.target 是什么属性
new.target 属性允许你检测函数或构造方法是否通过 new 运算符调用的,在通过 new 运算符被初始化的函数或构造方法中,new.target 返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target 的值是undefined。
3. 为什么一定要调用 super 才能实现继承?
因为 es6 的继承机制是继承在前,实例在后,先将父类的属性和方法加到一个空对象,然后再把空对象作为子类的实例; es5 是实例在前,继承在后
4. 说说你理解的 class
es5 之前生成实例对象是通过 new 构造函数来实现的,这种写法不够直观简洁,所以 es6 中引入 class 这个概念,通过 class 关键字可以定义类,它其实是一个语法糖,大部分功能 es5 也能做到,新的写法只是更清晰,更像面向对象编程的语法。
其基本语法是:
1 | class A { |
this
class 只能通过调用 new 实例化对象,其他调用方式都会报错,通过 new 操作符,将 this 指向当前实例化的对象。new.target 的属性指向创建实例对象的当前类。
super
- 子类继承父类的时候,必须在 constructor 中执行一次 super(),其作用是形成子类的 this 对象,将父类的实例属性和方法放到这个 this 对象。
- super 既可以作为对象使用,也可以当作函数调用。作为对象时,在普通方法中,指向父类的原型对象,在静态方法中,指向父类。
实例属性和原型属性
- constructor 中定义的属性属于实例对象上的,并非原型上的,但是类中定义的方法默认是原型方法,除非添加特殊关键字 static 或者 #
- 如何声明原型上的属性:
1 |
|
静态属性或方法 & 私有属性或方法
- static 关键字表示静态,不会被实例化,只能直接通过类来调用;但是可以被继承,可通过子类访问
#
关键字表示私有,早期解决方案为_属性名称
, 私有属性会被实例化,但是实例对象只能读取属性或方法。- 访问不存在的私有属性或方法会报错,普通属性只会返回
undefined
,此方法可以用来判断某个对象是否存在私有属性,但是需要增加 try catch,有个更好的判断私有属性是否存在的方法是 in 操作符, 他不会报错,返回一个布尔值。注意 in 只能在类的内部使用,另外对于 Object.create() Object.getPrototypeOf() 形成的继承是无效的,因为这种继承不会传递私有属性
1 | class C { |
继承
extends
关键字可以实现类之间的继承。
1 | class A {} |
与 es5 构造函数的区别
- class 不存在变量提升
- class 就是构造函数的一层包装,函数的许多特性都被 Class 继承, name 属性如果没有特别声明的话,总是返回 class 关键字后面的类名,
- 某个方法前加上
*
表示是一个 Generator 函数 - 类方法中的 this 默认指向实例化的对象,但是一旦单独使用,可能会报错
- class 只能通过 new 操作符调用,不能直接调用
- class 的方法是不可枚举的,通过 for in 不能访问
- 通过
class
创建的函数具有特殊的内部属性标记[[IsClassConstructor]]: true
- new 是构造函数生成实例化对象的命令, ex6 为 new 引入了 new.target 属性,此属性返回 new 作用于的那个构造函数或者类,因此这个属性可以用来确定构造函数是否通过 new 调用, class 中返回 class 名称,如果是子类调用,则返回子类名称。
1 | function Person(name) { |