1、简介
定义Class类
class Point {
_count = 0; // 实例属性(新写法)
constructor(x, y) {
// 实例属性、方法
this.x = x;
this.y = y;
}
toString() {
// 原型上的方法
return "(" + this.x + ", " + this.y + ")";
}
}
var point = new Point(2, 3);
point.toString(); // (2, 3)
point.hasOwnProperty("x"); // true x是实例上的属性
point.hasOwnProperty("y"); // true y是实例上的属性
point.hasOwnProperty("toString"); // false 方法不是实例上的
point.__proto__.hasOwnProperty("toString"); // true 方法是原型上的
改变原型方法的this指向
class Person {
constructor() {
// 构造函数的属性和方法
this.name = "zhangsan";
this.showName = this.showName.bind(this);
}
showName() {
// 原型上方法:this默认指向实例
return `名字为${this.name}`;
}
}
let p1 = new Person();
// 1、如果结构数来,默认指向全局
// 2、由于bind改变this指向,从新指向实例
let { showName } = p1; // 脱离了上下文
console.log(showName());
2、constructor ( 构造函数 )
- constructor 是默认方法,new对象实时,自动调用
- constructor 默认返回实例对象(即this),可以指定返回另外一个对象
class Foo {
constructor() {
// 默认返回实例对象,可手动指定对象
return Object.create(null);
}
}
new Foo() instanceof Foo;
// false
3、静态属性和方法
静态属性:
- Class 本身的属性,即Class.prop
- 不是定义在实例对象(this)上的属性
class MyClass {
static myStaticProp = 42;
constructor() {
console.log(MyClass.myStaticProp); // 42
}
}
class IncreasingCounter {
_count = 0;
get value() {
return this._count;
}
increment() {
this._count++;
}
}
静态方法:
- 不会被实例继承,直接通过类来调用
- 如果静态方法包含this关键字,这个this指的是类,而不是实例
- 父类的静态方法,可以被子类继承
//不会被实例继承,直接通过类来调用
class Foo {
static classMethod() {
return "hello";
}
}
Foo.classMethod(); // 'hello'
var foo = new Foo();
foo.classMethod();
//如果静态方法包含this关键字,这个this指的是类,而不是实例
class Foo {
// 静态方法中的this,指向类并非实例
static bar() {
this.baz();
}
static baz() {
console.log("hello");
}
baz() {
console.log("world");
}
}
Foo.bar(); // hello
// 父类的静态方法,可以被子类继承
class Foo {
static classMethod() {
return "hello";
}
}
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ", too";
}
}
Bar.classMethod(); // "hello, too"
4、继承(extend、super)
第一种情况:super作为函数调用时( 返回B的实例 )
- 代表父类A的构造函数,返回的是子类B的实例
- 内部的this指向的是B:相当于执行 A.prototype.constructor.call(this)
class A {
constructor() {
this.age = 18;
this.name = "张三";
this.getName = function () {
return this.name;
};
}
getAge() {
return this.age;
}
}
class B extends A {
constructor() {
// 相当于构造函数继承
super(); // A.prototype.constructor.call(this)
}
}
let a = new A();
let b = new B();
console.log(a.getName());
console.log(a.getAge());
// super对某个属性赋值,这时super就是this
// 赋值的属性会变成子类实例的属性
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3; //实质为B添加属性
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
第二种情况:super作为对象时
- 普通方法中:super 指向父类原型对象
- super.p()就相当于A.prototype.p()
- 定义在父类实例上的方法或属性,是无法通过super调用
- 静态方法中指向父类( 构造函数 )
- super将指向父类,而不是父类的原型对象
- 调用父类的方法时,内部的this指向当前的子类,而不是子类的实例
//普通方法中:super指向 A.prototype
class A {
constructor() {
this.p = 2;
}
}
class B extends A {
get m() {
// 普通方法中 super 指向父类原型对象
return super.p;
}
}
let b = new B();
b.m; // undefined
//用在静态方法之中,这时super将指向父类
class Parent {
static myMethod(msg) {
console.log("static", msg);
}
myMethod(msg) {
console.log("instance", msg);
}
}
class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg); //指向父类
}
myMethod(msg) {
super.myMethod(msg); //指向父类原型
}
}
//调用类方法
Child.myMethod(1); // static 1
//调用原型上的方法
var child = new Child();
child.myMethod(2); // instance 2