详解JavaScript原型与原型链
前置知识
在深入讲解JavaScript原型与原型链之前,需要了解以下概念:
- 对象
- 构造函数
- 实例
- 继承
原型
JavaScript中有一个对象,称为原型对象(prototype object),它指向一个JavaScript对象。每个JavaScript对象都有一个原型对象。
在对象定义时,可以通过Object.create()
方法,创建一个新对象,并指定newObject
的原型对象为someObject
。
在上述代码中,newObject
的原型对象为someObject
。
原型链
原型对象也可以有自己的原型。这种关系可以形成链状结构,被称作原型链(prototype chain)。
如果在一个对象中查找属性或方法时,找不到,它会沿着原型链一直向上查找,直到找到匹配的属性或方法或者查找到原型链的顶部,也就是Object.prototype
为止,如果在整个原型链上都没找到,返回undefined。
构造函数
构造函数(constructor)是通过new
关键字创建对象的特殊函数。构造函数可以用来创建特定类型的对象,相当于类的概念。
在构造函数中,可以使用this
关键字给对象添加属性和方法,同时可以使用new
关键字创建实例。
在上述代码中,Person
可以看作是一个构造函数,可以通过new
关键字创建实例。p
就是一个实例。
实例属性与原型属性
构造函数中定义的属性和方法,每一个实例都有一个独立的副本,称之为实例属性或方法。而通过原型对象定义的属性和方法,则被所有实例共享,称之为原型属性或方法。
在上述代码中,sayHello
方法是定义在Person
的原型对象上的,所以被所有实例共享。
对象继承
要实现继承,需要使用到原型链。
在JavaScript中,每个对象都有一个原型对象,可以通过重写对象的原型对象来实现继承。我们可以通过构造函数中的Object.create
方法,将父类的原型对象作为参数传入,生成一个新的对象,将这个新的对象作为子类的原型对象。
在上述代码中,Person
是父类,Student
是子类,Student
通过Object.create(Person.prototype)
来实现继承。
示例说明
示例1
现在有一个 Car
构造函数,它的原型对象上有一个 brand
属性,同时原型对象上还有一个 run
方法,可以让汽车行驶。现在我们创建了一个 Honda
的实例,用 console.log
依次输出它的属性和方法。
在上面的代码中,honda
是 Car
的一个实例,它继承了 Car
的原型对象上的 brand
属性和 run
方法。
示例2
现在有一个 Animal
构造函数,它拥有一个 type
属性。我们需要编写一个 Cat
构造函数,使它继承 Animal
,同时为 Cat
添加一个 name
属性。创建两个 Cat
的实例,用 console.log
依次输出它们的属性。
在上述代码中,Cat
通过 Object.create(Animal.prototype)
来实现继承 Animal
的原型对象,并重写它的构造函数。cat1
和 cat2
是 Cat
的两个实例,它们都拥有 Animal
的 type
属性和 Cat
的 name
属性。