JavaScript原型链

10 阅读2分钟

构造函数和原型对象

在js中,可以通过函数来创造对象,每个函数都有一个prototype属性,该属性是一个对象。所有通过该构造函数创造出来的对象,都可以共享prototype上的属性以及方法。

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    console.log('Hello, my name is ' + this.name);
};

const alice = new Person('Alice');
alice.sayHello(); // 输出: Hello, my name is Alice

可以在上面的例子中看到,在构造函数中并没有sayHello方法,后面通过在Personprototype上来创造一个方法,后续实例化对象之后就可以调用该方法了。

__proto__ 属性

每个JavaScript对象都有一个__proto__属性,这个属性指向对象的原型,也就是构造函数的prototype属性。当我们访问一个对象的属性时,如果该属性不存在,JavaScript会查找该对象的__proto__链,直至找到该属性,或者到达链的末尾。

console.log(alice.__proto__ === Person.prototype); // 输出: true

继承

使用原型链可以实现js上的继承

function Animal() {
    this.species = 'Animal';
}

Animal.prototype.makeSound = function() {
    console.log('Some generic sound');
};

function Dog(name) {
    this.name = name;
}

// 让 Dog 的原型指向 Animal 的实例,从而实现继承
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog; // 修正 constructor 属性

Dog.prototype.bark = function() {
    console.log('Woof! Woof!');
};

const dog = new Dog('Buddy');
console.log(dog.species); // 输出: Animal
dog.makeSound(); // 输出: Some generic sound
dog.bark(); // 输出: Woof! Woof!

Object 原型

所有对象的原型链最终都指向Object.prototype,如果在原型链中都找不到方法,最终会返回undefined

console.log(dog.toString()); // 输出: [object Object]
console.log(dog.__proto__.__proto__ === Object.prototype); // 输出: true
console.log(Object.prototype.__proto__ === null); // 输出: true

显示原型链

指的是构造函数上的prototype属性

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    console.log('Hello, my name is ' + this.name);
};

const alice = new Person('Alice');

Person创造出来的所有对象共享Person.prototype上的属性和方法

隐式原型链

指的是对象上的__proto__属性,这是创造对象时,js引擎自动设置的,指向创造这个对象的构造函数上的prototype属性。

function Animal() {
    this.species = 'Animal';
}

Animal.prototype.makeSound = function() {
    console.log('Some generic sound');
};

function Dog(name) {
    this.name = name;
}

// 让 Dog 的显式原型指向 Animal 的实例,从而实现继承
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog; // 修正 constructor 属性

Dog.prototype.bark = function() {
    console.log('Woof! Woof!');
};

const buddy = new Dog('Buddy');

Dog.prototype是显示原型链
buddy.__proto__是隐式原型链,指向Dog.prototype

console.log(Dog.prototype); // 显式原型链
console.log(buddy.__proto__); // 隐式原型链,指向 Dog.prototype

console.log(buddy.__proto__ === Dog.prototype); // 输出: true
console.log(Dog.prototype.__proto__ === Animal.prototype); // 输出: true
console.log(Animal.prototype.__proto__ === Object.prototype); // 输出: true
console.log(Object.prototype.__proto__ === null); // 输出: true