js中复杂类型都是对象类型(Object),而js中没有类(class)这个概念,那么其中的继承是如何实现的呢?
答案是构造函数

ES6中的class可以看作只是一个语法糖,它的绝大部分的功能,ES5都可以做到,新的class写法只是让原型的写法更加的清晰、更像面向对象编程的语法而已。

1. 前置知识

我们需要理解以下知识:
* 函数也是一种对象
* 普通函数和构造函数的区别
* 搞清楚 __proto__、prototype、constructor

需要记住以下两点:

  • __proto__、constructor属性是对象独有的
  • prototype属性是函数独有的

前面说过函数也是对象的一种,所以,函数同样有__proto__、constructor,即:
函数有:__proto__、constructor、prototype
对象有:__proto__、constructor

2. 构造函数

构造函数和普通函数在JavaScript中有几个主要区别:

  1. 创建对象:构造函数用于创建对象的实例,而普通函数用于执行特定的功能并返回一个值。

  2. 使用new关键字:在调用构造函数时,需要使用new关键字创建对象实例。这将触发以下操作:

    • 创建一个新的空对象
    • 将构造函数的作用域绑定到新对象(使this引用该对象)
    • 将新对象的原型指向构造函数的原型
    • 返回新的对象实例
  3. 对象属性和方法:构造函数经常用于在实例化过程中,给对象设置初始状态(例如属性和方法)。这些属性和方法在每个由构造函数创建的对象实例中都是独立的。普通函数一般不涉及对象的创建和状态管理,它可以执行一系列操作,但不会直接影响对象的属性和方法。

  4. 命名约定:通常,构造函数的命名习惯是首字母大写,以突出其作为构造函数的特殊功能和用途。

下面是一个示例,展示了构造函数与普通函数的区别:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;

this.greet = function() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
};
}

// 普通函数
function add(a, b) {
return a + b;
}

// 创建对象实例
const person = new Person('Alice', 25);

// 调用普通函数
const sum = add(2, 3);

在上述示例中,Person是一个构造函数,用于创建Person对象的实例。它具有属性nameage,以及方法greet。通过使用new关键字调用构造函数,并传递适当的参数,我们可以创建一个person对象。

另一方面,add是一个普通函数,用于执行简单的加法操作。它接受两个参数并返回它们的和。这里没有涉及创建对象实例或设置对象状态,只是执行了一个计算操作并返回结果。

总结起来,构造函数用于创建对象的实例,而普通函数用于执行特定的功能。构造函数可以用于为对象设置属性和方法,而普通函数则更专注于执行某些操作并返回结果。

小结: 构造函数通过new实例化,而普通函数没有这一过程,只是简单执行一段代码。

3. prototype

在此之前,我们先看一段Python代码:

1
2
3
4
5
6
7
8
9
10
11
class Person():

school = '一中'

def __init__(self,age):
self.age = age

a = Person(19)
b = Person(21)
print('a的学校为:', a.school)
print('b的学校为:', b.school)

上面代码中a、b学校相同

那在js中不同实例如何共享属性和方法呢,没错就是prototype!

1
2
3
4
5
6
7
8
9
var Parent = function () {
this.name = 'a'
Parent.prototype.school = '一中'
}

var p1 = new Parent();
var p2 = new Parent();
console.log(p1.school)
console.log(p2.school)

4. __proto__ 和原型链

1
console.log(p1.__proto__ === Parent.prototype) // true

__proto__ 指向该对象的原型对象,现已不推荐使用
推荐使用:Object.getPrototypeOf(person)

每个通过构造函数创建出来的实例对象,其本身有个属性__proto__,这个属性会指向该实例对象的构造函数的原型对象。

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会通过它的__proto__隐式属性,找到它的构造函数的原型对象,如果还没有找到就会再在其构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链

4. constructor

一句话:指向对象的构造函数

1
console.log(p1.constructor) // [Function: Parent]

参考

[1] https://juejin.cn/post/6984678359275929637#heading-2
[2] https://juejin.cn/post/7095651623812202533
[3] https://juejin.cn/post/7021416739887906830#comment