在JavaScript中,原型(Prototype)和原型链(Prototype Chain)是实现继承和对象间属性共享的核心机制。
原型(Prototype)
每个JavaScript对象(除了null之外)创建时都会自动获得一个原型对象,这个原型对象是通过对象的__proto__属性来访问的。原型对象本身也具有其自己的原型,除非它是Object.prototype,后者默认原型为null。
当你试图访问一个对象的某个属性或方法时,如果该对象本身没有这样的属性或方法,那么JavaScript引擎会沿着该对象的原型链继续查找,直到找到为止或者到达链的末端。
原型链(Prototype Chain)
当一个对象查找它的某个属性时,它不仅仅查找自身,还会查找它原型上的属性,如果还不行,就继续沿着原型链向上查找,直到到达Object.prototype。这就是所谓的“原型链”。
function Person() {}
Person.prototype = {
constructor: Person,
greet: function() {
console.log("Hello, " + this.name);
}
};
var person = new Person();
person.__proto__ === Person.prototype; // true
// 给实例添加属性
person.name = "Alice";
person.greet(); // 输出: Hello, Alice
// 继承关系
function Student() {}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.study = function() {
console.log(this.name + " is studying.");
};
var student = new Student();
student.name = "Bob";
student.greet(); // 输出: Hello, Bob
student.study(); // 输出: Bob is studying.
// 如果Student没有greet方法,但是有Person的原型,那么会从Person继承greet方法。
在这个例子中:
Person构造函数有一个原型对象Person.prototype,它定义了一个greet方法。
当我们创建Person的一个实例时,这个实例的__proto__指向了Person.prototype。
Student构造函数继承了Person的行为,因为它将它的原型设置为Person.prototype的一个副本,并且添加了一个study方法。
创建的Student实例student能够访问greet方法,这是因为当查找student.greet时,虽然student本身没有这个方法,但是沿着原型链可以找到Person.prototype.greet。