📕 重学JavaScript:你理解原型链吗?

简介: 在 JavaScript 中,我们整个编码过程都离不开”对象“,这个看起来简单的且基础的东西,却蕴含着着很多的知识点。也是我们理解原型链非常重要的一个辅助工具🔧。

📕 重学JavaScript:你理解原型链吗?

嗨,大家好!这里是道长王jj~ 🎩🧙‍♂️

你知道我们常说的JavaScript中的”对象“是什么吗?

我们在编码过程中经常使用存储很多信息📦。比如说,你可以用一个对象来描述一个人,他有什么名字,多大年纪,会做什么事情等等。

在 JavaScript 中,我们整个编码过程都离不开”对象“,这个看起来简单的且基础的东西,却蕴含着着很多的知识点。也是我们理解原型链非常重要的一个辅助工具🔧。

❓ 原型对象和构造函数有何关系?

我们先来举个例子:

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

Person.prototype.sayHello = function() {
   
  console.log("Hello, I'm " + this.name + ", and I'm " + this.age + " years old.");
};

var alice = new Person("Alice", 18);

alice.sayHello(); // Hello, I'm Alice, and I'm 18 years old.

var bob = new Person("Bob", 20);

bob.sayHello(); // Hello, I'm Bob, and I'm 20 years old.

// alice.sayHello === bob.sayHello

首先,我们定义了一个构造函数👷‍♂️,叫做 Person。构造函数就是一个特殊的函数,它可以用来创建对象。这个构造函数接受两个参数:name 和 age。当我们用 new 关键字来调用这个构造函数时,它会给新创建的对象设置两个属性:name 和 age。这两个属性的值就是我们传入的参数。

然后,我们在 Person 的原型对象👥上定义了一个方法,叫做 sayHello。原型对象就是一个包含了很多属性和方法的东西,它可以被所有由 Person 构造函数创建的对象所共享。这个方法会打印出对象的名字和年龄,并且说一句你好。我们用 this 关键字来指代当前调用这个方法的对象。

所以,我们首先就得到了这样一组关系

graph LR;
    A[Person构造函数] --prototype--> B[原型对象];
    B--constructor--> A;

接着,我们用 new 关键字来实例化👶 Person 构造函数,传入两个参数,创建了两个新的对象,分别叫做 Alice 和 bob。new 关键字会让 JavaScript 帮我们做以下几件事情:

  • 创建一个空的对象;
  • 把这个空对象的原型对象设置为 Person 的原型对象;
  • 把这个空对象作为 this 的值传给 Person 构造函数,并执行它;
  • 返回这个空对象(如果 Person 构造函数没有返回其他对象的话)。

所以,Alice 和 bob 这两个对象就有了 name 和 age 这两个属性,也有了 sayHello 这个方法。我们可以调用他们各自的 sayHello 方法,让它打印出自己的名字和年龄。注意,他们调用的是同一个方法。

我们就可以完善这一组关系:

graph LR;
    A[Person构造函数] --prototype--> B[原型对象];
    B--constructor--> A;
    A--new-->C[实例对象];
    C--_proto_-->B

这组关系说明,每个函数都有一个特殊的属性,叫做 prototype。这个属性指向了一个对象,叫做函数的原型对象👥。这个原型对象里面有一些属性和方法,它们可以被所有由这个函数创建的对象所共享。

当你用 new 关键字来调用一个函数时,这个函数就变成了一个构造函数👷‍♂️。它会返回一个全新的对象,叫做实例对象👶。这个实例对象有一个隐藏的属性,叫做 _proto_。这个属性指向了构造函数的原型对象。

❓ 什么又是原型链呢?

原型链是 JavaScript 中的一个非常重要的概念,它可以被形象地理解成由一些原型对象连起来的一条链子,用于表示对象之间的继承关系👩‍👧。在 JavaScript 中,每个对象都有一个隐藏的属性,叫做 _proto_。这个属性指向了这个对象的原型对象👥。如果我们在这个对象上找一个属性或方法,而这个对象本身没有这个属性或方法,那么就会沿着原型链向上找,直到找到这个属性或方法为止😊。

让我们来看一个简单的例子吧😉:

classDiagram
    Object <|-- Person
    Person <|-- p1
    Object : +__proto__
    Object : +constructor
    Person : +__proto__
    Person : +constructor
    p1 : +__proto__
    p1 : +constructor
    Object ..> Object: __proto__
    Person ..> Object: __proto__
    p1 ..> Person: __proto__

在这个例子中,Object 是所有对象的老祖宗👴,Person 是 Object 的孩子👶,p1 是 Person 的孩子👶。当我们创建一个 Person 实例时,它会继承 Object 的所有属性和方法。如果我们在 Person 实例上找一个属性或方法,而这个实例本身没有这个属性或方法,那么就会沿着原型链向上找,直到找到这个属性或方法为止。原型链最后会的原型对象是Object,Object最终会指向null 即原型链的终点。

💌 番外:如何判断原型上有没有这个属性

  • 对象的 hasOwnProperty() 来检查对象自身中是否含有该属性
  • 使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型链中有,也会返回 true
// 定义一个对象
var obj = {
   
  name: "Bing",
  age: 10
};

// 定义一个构造函数
function Person(name, age) {
   
  this.name = name;
  this.age = age;
}

// 给Person的原型添加一个属性
Person.prototype.gender = "male";

// 创建一个Person的实例
var p = new Person("Tom", 20);

// 使用hasOwnProperty()来检查对象自身中是否含有该属性
console.log(obj.hasOwnProperty("name")); // true
console.log(obj.hasOwnProperty("gender")); // false
console.log(p.hasOwnProperty("name")); // true
console.log(p.hasOwnProperty("gender")); // false

// 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型链中有,也会返回true
console.log("name" in obj); // true
console.log("gender" in obj); // false
console.log("name" in p); // true
console.log("gender" in p); // true

🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨

目录
相关文章
|
7月前
|
JavaScript 前端开发 安全
JavaScript原型链的使用
【4月更文挑战第22天】JavaScript中的原型链是理解继承的关键,它允许对象复用属性和方法,减少代码冗余。示例展示如何通过原型链实现继承、扩展内置对象、构造函数与原型链的关系以及查找机制。应注意避免修改`Object.prototype`,使用安全方式设置原型链,并谨慎处理构造函数和副作用。
|
2月前
|
JavaScript 前端开发 开发者
理解JavaScript中的原型链:基础与实践
【10月更文挑战第8天】理解JavaScript中的原型链:基础与实践
|
1月前
|
JavaScript 前端开发
JavaScript 原型链的实现原理是什么?
JavaScript 原型链的实现原理是通过构造函数的`prototype`属性、对象的`__proto__`属性以及属性查找机制等相互配合,构建了一个从对象到`Object.prototype`的链式结构,实现了对象之间的继承、属性共享和动态扩展等功能,为 JavaScript 的面向对象编程提供了强大的支持。
|
1月前
|
JavaScript 前端开发
原型链在 JavaScript 中的作用是什么?
原型链是 JavaScript 中实现面向对象编程的重要机制之一,它为代码的组织、复用、扩展和多态性提供了强大的支持,使得 JavaScript 能够以简洁而灵活的方式构建复杂的应用程序。深入理解和熟练运用原型链,对于提升 JavaScript 编程能力和开发高质量的应用具有重要意义。
|
1月前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
2月前
|
JavaScript 前端开发 开发者
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
33 1
|
2月前
|
JavaScript 前端开发 开发者
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
30 0
|
2月前
|
JavaScript 前端开发 开发者
原型链深入解析:JavaScript中的核心机制
【10月更文挑战第13天】原型链深入解析:JavaScript中的核心机制
38 0
|
2月前
|
JavaScript 前端开发 安全
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
30 0
|
4月前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
129 0