原型(Prototype)
在JavaScript中,每个对象(除了null
)都有一个与之关联的原型对象(prototype),这个原型对象可以包含属性和方法,这些属性和方法会被该对象"继承"。
关键点:
-
每个函数都有一个
prototype
属性:当创建一个函数时,JavaScript会自动为该函数添加prototype
属性。function Person() {} console.log(Person.prototype); // 输出一个对象
-
实例对象的
__proto__
属性:通过构造函数创建的实例对象会有一个__proto__
属性,指向构造函数的prototype
对象。const person = new Person(); console.log(person.__proto__ === Person.prototype); // true
-
原型上的属性和方法可以被所有实例共享:
Person.prototype.sayHello = function() { console.log('Hello!'); }; const p1 = new Person(); const p2 = new Person(); p1.sayHello(); // Hello! p2.sayHello(); // Hello!
原型链(Prototype Chain)
原型链是JavaScript实现继承的机制。当访问一个对象的属性或方法时,如果该对象本身没有这个属性,JavaScript会沿着原型链向上查找,直到找到该属性或到达原型链的末端(null
)。
原型链的构成:
-
实例对象 -> 构造函数的prototype -> Object.prototype -> null
function Person() {} const person = new Person(); // 原型链: // person -> Person.prototype -> Object.prototype -> null
-
更复杂的继承关系:
function Student() {} Student.prototype = new Person(); const student = new Student(); // 原型链: // student -> Student.prototype (Person实例) -> Person.prototype -> Object.prototype -> null
原型链查找示例:
function Person() {}
Person.prototype.name = 'Default';
const p1 = new Person();
console.log(p1.name); // 'Default' (从原型上找到)
p1.name = 'John';
console.log(p1.name); // 'John' (实例自身属性)
delete p1.name;
console.log(p1.name); // 'Default' (再次从原型上找到)
重要方法和属性
-
Object.getPrototypeOf(obj)
:获取对象的原型(推荐替代__proto__
) -
obj.hasOwnProperty(prop)
:检查属性是否是对象自身的(非继承的) -
prop in obj
:检查对象或其原型链上是否存在该属性 -
instanceof
:检查构造函数的prototype是否出现在对象的原型链上
实际应用
-
原型继承:
function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(`${this.name} makes a noise.`); }; function Dog(name) { Animal.call(this, name); // 调用父类构造函数 } // 设置原型链 Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; Dog.prototype.speak = function() { console.log(`${this.name} barks.`); }; const d = new Dog('Rex'); d.speak(); // Rex barks.
-
ES6类语法糖(底层仍然是基于原型):
class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } class Dog extends Animal { speak() { console.log(`${this.name} barks.`); } } const d = new Dog('Rex'); d.speak(); // Rex barks.
理解原型和原型链是掌握JavaScript面向对象编程的关键,也是理解JavaScript继承机制的基础。