class
constructor 构造方法
this 代表实例对象
方法之间不需要逗号分隔,加了会报错。
js
typeof Point // "function"
Point === Point.prototype.constructor // true
类的数据类型就是函数,类本身就指向构造函数。
类的所有方法都定义在类的prototype
属性上面
类的内部所有定义的方法,都是不可枚举的(non-enumerable)
ES6类内部定义的方法不可枚举;ES5可以
js
# es5
console.log(Object.getPrototypeOf(a));//['es5method']
#es6
console.log(Object.getPrototypeOf(a));//[]
point.hasOwnProperty('toString') // false
constructor方法
类的默认方法
通过 new 命令生成对象实例时,自定调用该方法。
没有显式定义的话,会默认添加
constructor 方法默认返回实例对象(即this)
实例的属性除非显式定义在其本身 (即定义在this
对象上),否则都是定义在原型上
类必须使用new
调用,否则会报错。
类的所有实例共享一个原型对象
取值函数(getter)和存值函数(setter)
js
class Point{
get prop() { return 'getter'; }
set prop(value) { console.log('setter: '+value); }
}
注意点
严格模式
类和模块的内部,默认就是严格模式,所以不需要使用use strict
指定运行模式。
不存在提升
类不存在变量提升(hoist)
这种规定的原因与下文要提到的继承有关,必须保证子类在父类之后定义。
Class 表达式
js
let Poin = class Point {
getName() {
console.log(Point.name, 'name')
}
}
let point = new Poin()
point.getName() // Point
console.log(Poin.name, 'Poin.name');//Point
console.log(Point1.name, 'Poin.name');//Point is not defined
Point
只在 Class 的内部可用,指代当前类。在 Class 外部,这个类只能用Poin
引用。
this 的指向
类的方法内部如果含有this
,它默认指向类的实例。
但是,如果将这个方法提取出来单独使用,this
会指向该方法运行时所在的环境
箭头函数内部的this
总是指向定义时所在的对象。
静态方法
static
关键字,不会被实例继承,而是直接通过类来调用
如果静态方法包含this
关键字,这个this
指的是类,而不是实例。
静态方法可以与非静态方法重名。
父类的静态方法,可以被子类继承。
静态方法也是可以从super
对象上调用的。
实例属性的新写法
js
class Point {
name;
constructor() {/**/}
}
静态属性
js
class Foo {}
Foo.prop = 1
# 或者
class Foo {
prop = 1;
}
私有方法和私有属性
只能在类的内部访问的方法和属性,外部不能访问。有利于代码的封装
在属性名之前,使用#
表示
js
class Foo {
#count = 0
}
只能在类的内部使用(
this.#count
)。如果在类的外部使用,就会报错
私有属性也可以设置 getter 和 setter 方法。
new.target 属性
该属性一般用在构造函数之中
返回new
命令作用于的那个构造函数。如果构造函数不是通过new
命令或Reflect.construct()
调用的,new.target
会返回undefined
,因此这个属性可以用来确定构造函数是怎么调用的。
js
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用 new 命令生成实例');
}
}
var person = new Person('张三'); // 正确
var notAPerson = Person.call(person, '张三'); // 报错
Class 内部调用
new.target
,返回当前 Class。
子类继承父类时,new.target
会返回子类。
js
class Fu {
constructor() {
console.log( new.target) //Son
}
}
class Son extends Fu {
constructor () {
super()
}
}
Class 继承
通过extends
关键字实现继承
super
关键字:表示父类的构造函数,用来新建父类的this
对象。
子类必须在constructor
方法中调用super
方法,否则新建实例时会报错。
这是因为子类自己的this
对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super
方法,子类就得不到this
对象。
子类的构造函数中,只有调用super
之后,才可以使用this
关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super
方法才能调用父类实例。
js
class Son extends Fu {
constructor() {
this.color = color // ReferenceError
super(x,y)
}
}
父类的静态方法,也会被子类继承。
Object.getPrototypeOf()
父类的静态方法,也会被子类继承。
js
Object.getPrototypeOf(ColorPoint) === Point
// true
super关键字
既可以当作函数使用,也可以当作对象使用。
作为函数调用时
作为函数调用时代表父类的构造函数,super
内部的this
指的是B
的实例
只能用在子类的构造函数之中,用在其他地方就会报错。
js
class A {}
class B extends A {
m() {
super(); // 报错
}
}
作为对象时
在普通方法中,指向父类的原型对象 ;在静态方法中,指向父类
如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
js
class A {
constructor() {this.p = 2}
say() {console.log('say', p)}
}
A.prototype.name = "Ren"
class B {
constructor() {
super()
this.p = 99
console.log(super.x) //undefined
super.say() //99
console.log(super.name) //Ren
this.b = 1
super.b = 2
console.log(super.b)//undefined
console.log(this.b)//2
}
}
获取属性 p 失败
获取方法 say 成功
获取属性 name 成功
注意:super.say()虽然调用的是 A.prototype.say(),但A.prototype()内部的this指向B所以输出的是 99
由于this
指向子类实例,所以如果通过super
对某个属性赋值,这时super
就是this
如果super
作为对象,用在静态方法之中,这时super
将指向父类,而不是父类的原型对象。
js
class Point {
static age = 18;
name = 19
static say() {
console.log(this.age, 'age')//18
console.log(this.name, 'name')//undefined
}
}
class Son extends Point {
static say() {
super.say()
}
}
Son.say()
在子类的静态方法中通过super
调用父类的方法时,方法内部的this
指向当前的子类,而不是子类的实例。
类的 Prototype 和 __proto__属性
Class 作为构造函数的语法糖,同时有prototype
属性和__proto__
属性,因此同时存在两条继承链。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
这两条继承链,可以这样理解:作为一个对象,子类(B
)的原型(__proto__
属性)是父类(A
);作为一个构造函数,子类(B
)的原型对象(prototype
属性)是父类的原型对象(prototype
属性)的实例。
js
class A {}
class B {}
Object.setPrototypeOf(B.prototype, A.prototype)// B 继承 A 的静态属性
Object.setPrototypeOf(B, A)// B 继承 A 的静态属性
const b = new B()
Object.setPrototypeOf
方法的实现。
js
Object.setPrototypeOf = function (obj, proto) {
obj.__proto__ proto
return obj
}
原生构造函数的继承
没看
Mixin 模式的实现
没看