js原型prototype链机制_js原型prototype链完整剖析

原型链是JavaScript实现继承和属性查找的核心机制。javascript中每个对象都有指向其原型对象的内部链接,构成原型链。访问对象属性时,若自身无此属性,则沿原型链向上查找,直至找到或到达NULL。函数的prototype属性指向构造出对象的原型,对象的__proto__属性(推荐用Object.getprototypeof())指向其构造函数的prototype,而原型对象的constructor指向关联构造函数。例如,person1.greet()通过person1.__proto__(即person.prototype)找到方法。继承通过将子类原型设为父类实例实现,如student.prototype = object.create(person.prototype)。理解原型链对代码设计、性能优化、排查问题等至关重要。避免原型链污染的方法包括不修改内置原型、使用object.create(null)创建无原型对象、用object.freeze()冻结对象。

js原型prototype链机制_js原型prototype链完整剖析

原型链机制是JavaScript实现继承的核心方式,它允许对象访问自身没有的属性或方法,转而去查找其原型对象,直至找到或到达原型链的顶端(null)。理解原型链对于深入掌握JS至关重要。

js原型prototype链机制_js原型prototype链完整剖析

解决方案

js原型prototype链机制_js原型prototype链完整剖析

JavaScript中,每个对象都有一个指向其原型对象的内部链接,这个链接就是原型链。当我们试图访问一个对象的属性时,如果对象自身没有这个属性,JS引擎会沿着原型链向上查找,直到找到该属性或到达原型链的终点——null。

  1. prototype 属性: 每个函数(除了箭头函数)都有一个prototype属性,它指向一个对象,这个对象通常被称为原型对象。

    js原型prototype链机制_js原型prototype链完整剖析

  2. __proto__ 属性: 每个对象(除了 null )都有一个 __proto__ 属性,它指向创建该对象的构造函数的原型对象。注意,__proto__ 已经被标记为不推荐使用,推荐使用 Object.getPrototypeOf() 和 Object.setPrototypeOf() 来访问和修改对象的原型。

  3. constructor 属性: 原型对象默认有一个constructor属性,指向关联的构造函数。

理解这三个属性之间的关系是理解原型链的关键。例如:

function Person(name) {   this.name = name; }  Person.prototype.greet = function() {   console.log("Hello, my name is " + this.name); };  const person1 = new Person("Alice"); person1.greet(); // 输出 "Hello, my name is Alice"  console.log(person1.__proto__ === Person.prototype); // true console.log(Person.prototype.constructor === Person); // true

在这个例子中,person1对象的__proto__属性指向Person.prototype,因此person1可以访问Person.prototype上的greet方法。

原型链的查找过程:

当访问person1.greet()时,JS引擎首先检查person1对象自身是否具有greet属性。如果没有,则沿着person1.__proto__(即Person.prototype)向上查找。因为Person.prototype上有greet方法,所以找到了并执行。如果Person.prototype上也没有greet方法,会继续沿着Person.prototype.__proto__向上查找,直到找到或到达原型链的顶端null。

如何利用原型链实现继承?

JavaScript通过原型链实现继承。子类构造函数的原型指向父类的一个实例,这样子类就可以继承父类的属性和方法。

function Student(name, studentId) {   Person.call(this, name); // 调用父类构造函数,继承属性   this.studentId = studentId; }  Student.prototype = Object.create(Person.prototype); // 关键:设置子类原型为父类原型的一个实例 Student.prototype.constructor = Student; // 修正constructor指向  Student.prototype.study = function() {   console.log(this.name + " is studying."); };  const student1 = new Student("Bob", "12345"); student1.greet(); // 继承自Person student1.study(); // Student自身的方法

这里,Object.create(Person.prototype)创建了一个新对象,该对象的原型是Person.prototype。然后,将Student.prototype指向这个新对象,从而实现了继承。 需要注意的是,需要手动修正Student.prototype.constructor的指向,否则它仍然指向Person。

为什么理解原型链对于javascript开发至关重要?

原型链是JavaScript中实现继承和共享属性的关键机制。不理解原型链,很难理解JS中对象创建、属性查找和继承的工作方式,进而影响代码的编写效率和质量。它直接影响着你如何设计对象,如何组织代码,以及如何解决一些常见的JS问题,例如:

  • 性能优化: 理解原型链可以避免不必要的属性查找,提高代码性能。
  • 代码复用: 通过原型链实现继承,可以有效地复用代码,减少代码冗余。
  • 框架设计: 很多JS框架都依赖原型链来实现其核心功能。
  • 排查问题: 当遇到属性访问问题时,可以通过原型链来追踪属性的来源。

__proto__、prototype 和 constructor 之间的区别是什么?

  • prototype:是函数才有的属性,指向该函数作为构造函数创建的对象的原型。
  • __proto__:是对象才有的属性,指向创建该对象的构造函数的原型。
  • constructor:是原型对象才有的属性,指向关联的构造函数。

三者之间存在关联:对象的__proto__属性指向其构造函数的prototype属性,而构造函数的prototype属性的constructor属性又指向该构造函数本身。

如何避免原型链污染?

原型链污染是指修改了内置对象的原型,导致所有基于该原型创建的对象都受到影响。这可能会导致意想不到的错误和安全问题。

例如,如果修改了Object.prototype,那么所有对象都会受到影响。

避免原型链污染的一些方法:

  1. 不要直接修改内置对象的原型: 尽量避免修改Object.prototype、Array.prototype等内置对象的原型。
  2. 使用 Object.create(null) 创建无原型对象: 如果需要创建一个完全干净的对象,可以使用Object.create(null),它创建的对象没有原型链。
  3. 使用 Object.freeze() 冻结对象: 可以使用Object.freeze()冻结对象,使其无法被修改。
  4. 注意第三方库: 使用第三方库时,要仔细检查其代码,避免其修改内置对象的原型。

理解原型链是成为一名优秀的JavaScript开发者的基石。希望以上内容能够帮助你更深入地理解JS原型链机制。

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享