第119篇: JavaScript 类

好家伙,我们先来复习一下

 

关于Java,类的三大特征:

1、封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

2、继承,继承性更符合认知规律,使程序更易于理解,同时节省不必要的重复代码。

3、多态,体现为覆盖和重载,Js没有重载,有时子类并不想原封不动地继承父类的方法,而是想作一定的修改。

这时我们可以对方法进行重写,也就是方法覆盖

 

 

1.类的定义

先来试用一下

function functionPerson(){}
class classPerson{
}

console.log(functionPerson.prototype)
console.log(classPerson.prototype)

(猜猜看跑完什么结果?)

 

 

 

所以我们知道,虽然ECMAScript 6类表面上看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然是原型和构造函数的概念。

(还是原型链那一套)

 

 

2.类的构造函数

类可以包含构造函数方法、实例方法、获取函数、设置函数和静态类方法,但这些都不是必需的。

使用new操作符实例化Person的操作等于使用new调用其构造函数。

唯一可感知的不同之处就是,JavaScript解释器知道使用new和类意味着应该使用constructor函数进行实例化。

使用new调用类的构造函数会执行如下操作。

(1)在内存中创建一个新对象。

(2)这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性。

(3)构造函数内部的this被赋值为这个新对象(即this指向新对象)。

(4)执行构造函数内部的代码(给新对象添加属性)。

(5)如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

 

3.原型方法

类定义语法把在类块中定义的方法作为原型方法。

(例子跟下面的放一起了)

 

4.静态类方法

可以在类上定义静态方法。这些方法通常用于执行不特定于实例的操作,也不要求存在类的实例。

与原型成员类似,静态成员每个类上只能有一个。

静态类成员在类定义中使用static关键字作为前缀。在静态成员中,this引用类自身。其他所有约定跟原型成员一样:

  class Person {
    constructor() {
      // 添加到this的所有内容都会存在于不同的实例上
      this.locate = () => console.log('instance', this);
    }
    // 定义在类的原型对象上
    locate() {
      console.log('prototype', this);
    }
    //定义在类本身上
    static locate(){
      console.log('class', this);
    }
  }
  let p = new Person();
  p.locate();                     // instance, Person {}
  Person.prototype.locate();   // prototype, {constructor: ... }
  Person.locate();               // class, class Person {}

 

(书中原例,)

 

 

 

 

5.继承extend

类继承使用的是新语法,但背后依旧使用的是原型链。

使用extends关键字,就可以继承任何拥有[[Construct]]和原型的对象。

很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数(保持向后兼容)

class Person {}
function Cat() {}
class Somebody extends Person {}
class Bosicat extends Cat {}

let a = new Somebody();
let b = new Bosicat();
console.log(a instanceof Person);
console.log(b instanceof Cat);

 

 

 

 

(通过继承function这点看出,Js终于洗清了他的嫌疑,它确实和Java没关系)

 

 

6.super关键字

派生类的方法可以通过super关键字引用它们的原型。

这个关键字只能在派生类中使用,而且仅限于类构造函数、实例方法和静态方法内部。

在类构造函数中使用super可以调用父类构造函数。

class Cat{
    constructor(){
        this.age = '2'
    }
}

class Bosicat extends Cat{
    constructor(){
        super();
        console.log(this);
    }
}

new Bosicat;

 

 

 

 

 

在使用super时要注意几个问题。

(1)super只能在派生类构造函数和静态方法中使用。

(2)不能单独引用super关键字,要么用它调用构造函数,要么用它引用静态方法

(3)调用super()会调用父类构造函数,并将返回的实例赋值给this。

(4)super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入。

(5)如果没有定义类构造函数,在实例化派生类时会调用super(),而且会传入所有传给派生类的参数

(6)在类构造函数中,不能在调用super()之前引用this

(7)如果在派生类中显式定义了构造函数,则要么必须在其中调用super(),要么必须在其中返回一个对象。

 

posted @ 2022-12-31 21:19  养肥胖虎  阅读(44)  评论(0编辑  收藏  举报