如何理解JavaScript的原型和原型链?

6次阅读

共计 1790 个字符,预计需要花费 5 分钟才能阅读完成。

之前有朋友问怎么去理解原型和原型链的问题。这个问题,在面试中,很多同学经常都会遇到。这里给大家讲讲,方便大家记忆。JavaScript 的特点 JavaScript 是一门直译式脚本语言,是一种动态类型、基于原型的语言。JavaScript 的灵活性不亚于 C ++,你可以使用 JavaScript 尝试不同的程序设计范型。比如类 jQuery 风格的函数式编程、基于过程的指令式编程、以及基于原型的面向对象编程。不同于 Java、C# 等面向对象语言,JavaScript 采用基于原型的继承方式。为啥会有原型和原型链?1994 年,网景公司(Netscape)发布了 Navigator 浏览器 0.9 版,但是刚开始的 Js 没有继承机制,更别提像同时期兴盛的 C ++ 和 Java 这样拥有面向对象的概念。在实际的开发过程中,工程师们发现没有继承机制很难解决一些问题,必须有一种机制能将所有的对象关联起来。Brendan Eich 鉴于以上情况,但不想把 Js 设计得过为复杂,于是引入了 new 关键词和 constructor 构造函数来简化对象的设计,引入了 prototype 函数对象来包含所有实例对象的构造函数的属性和方法,引入了 proto 和原型链的概念解决继承的问题。原型模式每个函数都有一个 prototype(原型) 属性这个属性都有一个指针,指向一个对象这个对象包含由特定类型所有实例共享的属性和方法使用原型的好处是可以让所有对象实例共享它包含的方法和属性通过 in 操作符和 hasOwnProperty 来判断给定属性是来自于原型还是实例 in- true 代表属性在对象中存在 来自实例或者来自原型 hasOwnProperty- true 代表属性来自于实例 是实例属性原型链 ECMAScript 中只支持实现继承,而且是通过原型链的方式来实现的。所以原型链是 JavaScript 实现继承的一种重要方式。用户定义类型的原型链我们一般如何来检查 JavaScript 的变量数据类型?一般我们都是通过 instanceof 关键字,可以基于原型链来检测变量的类型。我们可以先构造一个原型链,再用 instanceof 来检测类型:​​​​由上面讲的 instanceof 的结果,可以判断这些类型的继承层级:​​事实上 instanceof 是通过原型链来检测类型的,例如 L instanceof R:如果 R.prototype 出现在了 L 的原型链上则返回 true,否则返回 false。用 JavaScript 来描述 instanceof 的实现逻辑是这样的:​​JavaScript 原型链先给大家看一个 JavaScript 的原型链结构图。理解原型链的小技巧:将__proto__箭头视作泛化(子类到父类)关系!那么图中所有的虚线将构成一个继承层级,而实线表示属性引用。图中给出了 Object.prototype.__proto__ == null,但它还没有标准化,在 Chrome、Safari 和 Node.js 下它是不同的东西。但可以看到 JavaScript 中所有对象的共同隐式原型为 Object.prototype,它的上一级隐式原型是什么已经不重要了,因为它不会影响所有内置对象以及用户定义类型的原型链结构。上图其实已经解释了不同内置对象 instanceof 的行为,我们来看 Function 和 Object 的特殊之处:Object 是由 Function 创建的:因为 Object.__proto__ === Funciton.prototype;同理,Function.prototype 是由 Object 创建的;Funciton 是由 Function 自己创建的!Object.prototype 是凭空出来的!现在我们可以解释特殊对象的 instance 行为了:​​另外可以看到当你声明一个函数(比如 Animal)时,Animal.prototype 会自动被赋值为一个继承自 Object 的对象,而且该对象的 constructor 等于 Animal。即:​​值得注意的是 Animal 如果被 Cat 继承,Cat 实例(比如 cat)的 constructor 仍然是 Animal。​​总结 1. 每个函数对象都有一个 prototype 属性,这个属性就是函数的原型对象。2. 原型链是 JavaScript 实现继承的重要方式,原型链的形成是真正是靠__proto__ 而非 prototype。
喜欢文章的可以关注小编~

正文完
 0