likes
comments
collection
share

constructor 内部和外部定义的方法有哪些区别?

作者站长头像
站长
· 阅读数 66

前言

constructor 是一种用于创建和初始化 class 创建的对象的特殊方法。在一个类中只能有一个 constructor,本质是一个构造函数,如果一个类不指定一个构造函数(constructor), 则使用一个默认的构造函数(constructor)。

示例

本文我们通过一个示例,来了解一下在 constructor 内部和外部定义的方法有哪些区别?

class Person {
  constructor(name) {
    this.name = name
    this.say1 = () => {
      console.log("我在里面", this.name)
    }
  }
  say2() {
    console.log("我在外面", this.name)
  }
}

const A = new Person("A")
const B = new Person("B")

A.say1()  // 我在里面 A
A.say2()  // 我在外面 A

在上述代码中,我们首先创建了一个 Person 类,让 name 属性和 say1 方法定义在 constructor 内部,而 say2 方法定义在 constructor 外部。然后通过 new 创建了实例 A 和 实例 B,通过 A 去调用 say1say2 方法,查看输出结果。通过结果我们可以看出在 constructor 内部和外部定义的方法中,this.name 的结果都是相同的,那么它们就没有区别吗?当然不是,接下来我们就来分析一下这样定义的方法到底有哪些区别。

区别

  1. 在构造函数(constructor)内部定义的方法是在每个对象实例上创建了一个新的函数。而在构造函数(constructor)外部定义的方法是在原型对象(Person.prototype)上创建的。

我们可以通过 __proto__ 来进行验证:

class Person {
  constructor(name) {
    this.name = name
    this.say1 = () => {
      console.log("我在里面", this.name)
    }
  }
  say2() {
    console.log("我在外面", this.name)
  }
}

const A = new Person("A")
const B = new Person("B")

console.log(A.__proto__.say1)  // undefined
console.log(A.__proto__.say2)  // ƒ say2() { ... }

通过查看输出结果,我们可以知道在 constructor 外部定义的方法是在原型对象(Person.prototype)上创建的,而在 constructor 内部定义的方法无法通过原型链进行查找。

  1. 在构造函数(constructor)内部定义的方法是各个实例对象独有的。而在构造函数(constructor)外部定义的方法是所有实例对象共享的。

我们可以通过判断不同实例调用的方法是否相同来进行验证:

class Person {
  constructor(name) {
    this.name = name
    this.say1 = () => {
      console.log("我在里面", this.name)
    }
  }
  say2() {
    console.log("我在外面", this.name)
  }
}

const A = new Person("A")
const B = new Person("B")

console.log(A.say1 === B.say1)  // false
console.log(A.say2 === B.say2)  // true

通过查看输出结果,我们可以知道在 constructor 内部定义的方法是各个实例独有的,多个实例进行调用相当于在内存中创建了多个方法,地址不同,结果当然也就不同。而在 constructor 外部定义的方法是所有实例对象共享的,在内存中该方法的地址是一样的,所以结果也就相同。

  1. 在构造函数(constructor)内部定义的方法可以被 Object.keys() 遍历。而在构造函数(constructor)外部定义的方法不能被 Object.keys() 遍历。
class Person {
  constructor(name) {
    this.name = name
    this.say1 = () => {
      console.log("我在里面", this.name)
    }
  }
  say2() {
    console.log("我在外面", this.name)
  }
}

const A = new Person("A")
const B = new Person("B")

console.log(Object.keys(A))  // ['name', 'say1']
console.log(Object.keys(B))  // ['name', 'say1']

通过查看输出结果,我们发现 Object.keys() 只能遍历在 constructor 内部定义的属性和方法,而对于在 constructor 外部定义的 say2() 方法并不能被遍历到。这是因为 Object.keys() 并不会遍历原型链上的属性和方法。

通过对第一个区别进行延伸,我们也不难去推断出第二个和第三个区别,所以最好就是将知识串联起来,便于理解。

最后

以上就是笔者对于这一知识点的浅显理解,如果大家觉得还有可以补充的话,欢迎在评论区留言~

转载自:https://juejin.cn/post/7248951438742798391
评论
请登录