JS原型和原型链

286 阅读4分钟

作为一个初入前端的小白菜,我相信对原型链一直觉得难以理解,对整个原型链的了解比较模糊。理解原型链是深入学习js的一小步,在查阅多篇文献以后,有一些小的理解。

对象

1、在JS中对象就是一组无序的键值对的集合,对象由属性和方法组成 。 2、所有的函数本质上是一个对象。
3、所有对象都是引用类型(保存的地址)。
4、普通对象是通过new 函数创建的。
5、函数对象的__proto__都指向Function.prototype

普通对象是通过new 函数创建的.jpg

原型(prototype)

1、在JS中,所有函数都有一个特殊属性prototype称之为函数原型对象。
2、默认情况下,原型对象是一个普通的Object对象。
3、默认情况下,原型对象中有一个属性constructor,他指向的是构造函数本身。
4、原型对象的属性和方法会被继承到所有通过原型链与他相连的对象。

小结:在 JS 里,函数都有个prototype属性,它连着原型对象。这对象默认是普通对象,能放东西,里面有个constructor指向函数本身。它的属性和方法能通过原型链被相关对象拿去用,像 Car 函数创建的对象能从 Car.prototype 继承。原型对象就是让东西能共享和继承的关键。 image.png

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

每个函数都有原型对象.jpg

原型中的constructor指向函数本身.jpg

隐式原型(__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!'

隐式原型的指向.jpg

原型链(prototype chain)

1、原型链是JS用于实现继承和属性查找的一种机制。它是一个由对象的隐式原型(__proto__)连接起来的链状结构。
2、原型链顶端就是Object.prototype
3、原型链的终点是null(Object.prototype.__proto__)

小结:每个对象都有一个原型(prototype),它指向另外一个对象,而指向的对象又存在属性(__proto__)指向另外一个对象,当我们访问对象的属性时,会先在对象定义的属性中进行查找,没找到就会沿着__proto__一路向上查找,最终形成一个链式结构,这整个链式结构就叫做原型链
注意Function.prototypeFunction.__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();

Function.jpg

总结

一、原型

  • 函数的prototype属性是原型对象,通过函数创建的对象,其隐式原型__proto__指向该函数原型。
  • 作用是实现属性和方法共享及支持继承,如Person.prototype上的方法可被Person创建的对象共用。

二、原型链

  • 由对象隐式原型__proto__连接而成,用于属性查找,找不到就沿链向上找,直到null
  • myDog -> Dog.prototype -> Animal.prototype -> null,实现继承和属性方法调用。
  • 注意事项:概念抽象,有属性覆盖风险,长链或频繁查找可能影响性能。

注意:现代JS__proto__(隐式原型)已经被弃用
详细参考:Object.prototype.__proto__