如果是使用过 C++ 或 Java 这类语言的小伙伴,肯定对 OOP 不陌生。而 JavaScript 没有类,又是怎么样实现继承呢?准确来说,前者是基于类的继承机制,而后者是基于原型的继承机制。
听到这,你可能会反驳,JavaScript 不是有class
关键字吗?诚然,ES6 之后引入了class
关键字,让 JavaScript 有了“类”。但它更像是一种语法糖,只是简化了语法,本质上还是基于原型。
可以说,是构造函数和原型对象共同组成了 JavaScript 中“类”的概念。为了方便理解,先来看张图。
如果我们定义了一个构造函数,那么通过构造函数的prototype
属性就能访问到原型对象,而通过原型对象的constructor
属性又能访问到构造函数。这就是组成了一个“类”,而构造函数的函数名就是这个“类”的类名。
在此基础上,我们再加上new
关键字,就可以创建出一个实例对象了。
如果将这个实例对象在浏览器的控制台中打印出来,会看到实例对象上有一个[[Prototype]]
属性,它指向这个“类”中的原型对象。只不过,我们在编写 js 代码时使用的是__proto__
。
至此,我已经对 JavaScript 中的“类”有了一个基本的认识。但是,要怎么才能实现文章开头提到的继承呢?刚刚提到的__proto__
就是关键。
通过__proto__
属性,我们能给某个原型对象再指定它的原型。这样能够把一系列的原型对象串起来,也就是所谓的“JavaScript 原型链”。因此,我们也就实现了各个“类”之间的继承。
这么看起来,要实现继承确实挺麻烦的。所以,ES6 也给我们提供了更加方便的语法,我们可以使用class
和extends
关键字来实现“类”的继承。不过归根结底,JavaScript 还是基于原型的继承机制,认识原型链也能帮助我们更好地理解 JavaScript 中的继承。