继续补档,发现这块内容其实蛮多的。后面估计还会有两篇(怎么还有两篇啊喂!),分别是 JavaScript执行原理·补 和 JavaScript部分特性,这周不知道能不能搞定。
先看 JS 原型链吧。
JS 继承机制设计
1994年,网景公司(Netscape)发布了 Navigator v0.9,轰动一时。但当时的网页不具备交互功能,数据的交互全部依赖服务器端,这浪费了时间与服务器资源。
网景公司需要一种网页脚本语言实现用户与浏览器的互动,工程师 Brendan Eich 负责该语言的开发。他认为这种语言不必复杂,只需进行一些简单操作即可,比如填写表单。
可能是受当时面向对象编程(object-oriented programming)的影响,Brendan 设计的 JS 里面所有的数据类型都是对象(object)。他需要为 JS 设计一种机制把这些对象连接起来,即“继承”机制。
继承允许子类继承父类的属性和方法,并且可以在子类中添加新的属性和方法,实现代码的重用和扩展性。
出于设计的初衷,即“开发一种简单的网页脚本语言”,Brendan 没有选择给 JS 引入类(class)的概念,而是创造了基于原型链的继承机制。
在 Java 等面向对象的语言中,一般是通过调用 class 的构造函数(construct)创建实例,如:
class Dog {
public String name;
public Dog(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Rover");
System.out.println(dog.name); // Rover
}
}
Brendam 为 JS 做了简化设计,直接对构造函数使用new
创建实例:
function Dog(name) {
this.name = name;
}
var dog = new Dog("Rover");
console.log(dog.name) // Rover
这种设计避免了在 JS 中引入 class,但这引出一个问题:JS 的实例该如何共享属性和方法?基于构造函数创建的实例都是独立的副本。
先看看 Java 是如何基于 class 实现属性和方法共享的:
class Animal {
public void eat() {
System.out.println("Animal is eating");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking");
}
}
class Cat extends Animal {
public void meow() {
<