作为一个初入前端的小白菜,我相信对原型链一直觉得难以理解,对整个原型链的了解比较模糊。理解原型链是深入学习js的一小步,在查阅多篇文献以后,有一些小的理解。
对象
1、在JS中对象就是一组无序的
键值对的集合,对象由属性和方法组成 。 2、所有的函数本质上是一个对象。
3、所有对象都是引用类型(保存的地址)。
4、普通对象是通过new 函数创建的。
5、函数对象的__proto__都指向Function.prototype
原型(prototype)
1、在JS中,所有函数都有一个特殊属性
prototype称之为函数原型对象。
2、默认情况下,原型对象是一个普通的Object对象。
3、默认情况下,原型对象中有一个属性constructor,他指向的是构造函数本身。
4、原型对象的属性和方法会被继承到所有通过原型链与他相连的对象。小结:在 JS 里,函数都有个
prototype属性,它连着原型对象。这对象默认是普通对象,能放东西,里面有个constructor指向函数本身。它的属性和方法能通过原型链被相关对象拿去用,像 Car 函数创建的对象能从 Car.prototype 继承。原型对象就是让东西能共享和继承的关键。
function Car() {} // 在原型对象上添加方法
Car.prototype.drive = function () { console.log("The car is driving."); };
const myCar = new Car(); myCar.drive(); // 输出:The car is driving.
console.log(myCar.constructor === Car); // 输出:true
隐式原型(__proto__)
1、所有的对象都有一个
__proto__属性称之为隐式原型。
2、默认情况下,隐式原型指向创建该对象的函数的原型。
3、给函数原型上加入方法(成员)/属性叫猴子补丁,会导致原型污染。
4、在JavaScript中,查找对象成员,先查自身,没有查隐式原型,再没有沿原型链查找,直至找到或原型链顶端。小结:JavaScript 中,隐式原型(
__proto__)是对象内部用于构建原型链的属性。它决定对象属性和方法的查找路径,实现继承。创建对象实例时关联相关prototype,对象字面量默认指向Object.prototype。可通过__proto__改原型继承,但不建议,现代用Object.getPrototypeOf()和Object.setPrototypeOf()更好。隐式原型使继承灵活,修改需谨慎,理解它对掌握 JavaScript 对象模型和继承机制很重要。
let animal = { eat: function() { console.log('Eating...'); } };
let dog = { bark: function() { console.log('Woof!'); } };
dog.__proto__ = animal;
dog.bark(); // 输出 'Woof!'
dog.eat(); // 输出 'Eating...',
//因为在dog对象本身没有eat方法,会通过隐式原型__proto__找到animal对象中的eat方法
function Person() {}
Person.prototype.sayHello = function() {
console.log('Hello!');
};
let p1 = new Person();
let p2 = new Person();
p1.sayHello(); // 输出 'Hello!'
p2.sayHello(); // 输出 'Hello!'
原型链(prototype chain)
1、原型链是JS用于实现继承和属性查找的一种机制。它是一个由对象的隐式原型(
__proto__)连接起来的链状结构。
2、原型链顶端就是Object.prototype
3、原型链的终点是null(Object.prototype.__proto__)小结:每个对象都有一个原型(
prototype),它指向另外一个对象,而指向的对象又存在属性(__proto__)指向另外一个对象,当我们访问对象的属性时,会先在对象定义的属性中进行查找,没找到就会沿着__proto__一路向上查找,最终形成一个链式结构,这整个链式结构就叫做原型链
注意:Function.prototype和Function.__proto__都是Function原型,Function.prototype.__proto是Oject.prototype。
function Animal() {}
Animal.prototype.eat = function() { console.log("Eating..."); };
function Dog() {}
Dog.prototype = new Animal();
let myDog = new Dog();
myDog.eat();
总结
一、原型
- 函数的
prototype属性是原型对象,通过函数创建的对象,其隐式原型__proto__指向该函数原型。 - 作用是实现属性和方法共享及支持继承,如
Person.prototype上的方法可被Person创建的对象共用。
二、原型链
- 由对象隐式原型
__proto__连接而成,用于属性查找,找不到就沿链向上找,直到null。 - 如
myDog -> Dog.prototype -> Animal.prototype -> null,实现继承和属性方法调用。 - 注意事项:概念抽象,有属性覆盖风险,长链或频繁查找可能影响性能。
注意:现代JS
__proto__(隐式原型)已经被弃用
详细参考:Object.prototype.__proto__