JavaScript专题-原型链

简介: JavaScript专题-原型链此专题系列为又一次重新阅读了《高程4》后,对JavaScript重难点进行了梳理,希望能融会贯通,加深印象,更进一步...原型定义这里通过多方面对原型进行描述,因为其实大家多多少少都接触过原型相关的知识,不理解可能只需要某句话就能点破,希望对你有所帮助。

JavaScript专题-原型链

此专题系列为又一次重新阅读了《高程4》后,对JavaScript重难点进行了梳理,希望能融会贯通,加深印象,更进一步...

原型定义


这里通过多方面对原型进行描述,因为其实大家多多少少都接触过原型相关的知识,不理解可能只需要某句话就能点破,希望对你有所帮助。

原型prototype其实就是每个构造函数的一个内置属性,或者说每个函数都有这样一个属性,毕竟所有函数都可以做构造函数,当然箭头函数除外,那只是JS简化一些写法的机制,与普通函数有一定区别。任何时候我们在创建一个普通函数时,都会按照特定的规则为这个函数创建一个prototype属性,所以我们可以访问它。

function Person(name) {
    console.log('exec...');
    this.name = name
}
Person.prototype.city = 'Beijing'
Person.prototype.skill = function(){
    console.log('coding...');
}


这个prototype属性是一个对象,这个原型对象上的属性和方法都可以被对应的构造函数创建的实例所共享,这点也是原型最重要的性质之一。

const p1 = new Person('Justin3go');
const p2 = new Person('XXX');
console.log(p1.name, p2.name);
console.log(p1.city, p2.city);
p1.skill();
p2.skill();
exec... 
exec... 
Justin3go XXX 
Beijing Beijing
coding...
coding...


值得注意的是,实例并没有prototype属性,只有构造函数拥有该属性。如果你了解new操作符的过程的话可能对此比较清楚,它只是在实例化的过程中会把构造函数的prototype赋值给实例的一个内部特性指针[[Prototype]]上,然后浏览器会在每个实例对象上暴露__proto__执行访问操作。后续ES6才规范了Object.getPrototype()方法访问原型

我们可以把原型对象作为每个相关实例的上层作用域,通俗来说就是实例上没有的变量名,会往上层作用域找,这里就是先找的自己的原型对象里面是否包含该变量名;既然是作用域,当实例上包含和原型同名的方法或属性时,访问的就只会是实例自己定义的了,这就是常说的覆盖。

这个原型对象中除了自定义的属性和方法,还有就是一个特殊的属性叫做constructor,其指向构造函数。这样,所有的实例都可以访问该属性从而获取自己的构造函数了

深入理解原型


这里我们再来梳理一下这个过程:

  1. 首先我们创建了一个构造函数想要去生成一些实例对象
  2. JS会自动给这个构造函数生成一个原型对象
  3. 然后我们基于原型的特性把想要共享的属性和方法添加到了构造函数的原型上
  4. 之后我们实例化的时候会将构造函数的原型对象赋值给实例对象中的内部指针,注意赋值不是复制,只是指向,实例和构造函数的原型都是一个
  5. 然后我们访问实例对象中的属性,发现实例本身没有,就会自动去找原型上的

然后在这个例子中,我们再来梳理一下关于构造函数、实例、原型的一个关系,下面这个图就可以非常清晰明了的表达了:

原型链


在JavaScript中,我们都知道每个对象都有一个[[Prototype]]指针指向其原型对象,而原型对象也是对象,所以原型对象也包含一个[[Prototype]]指针指向更上一层的原型对象。这就是形成我们常说的原型链的基础。

我们再简化一下这张图,让你对链的加深一下记忆:

关于原型对象中的constructor属性


这里说说我们经常见到的一个问题就是为什么不要使用对象的constructor属性来判断该对象属于哪类:


const arr1 = new Array();
console.log(arr1.constructor === Array);
function Person(){};
const p1 = new Person();
console.log(p1.constructor === Person);


true
true


constructor虽然可以拿来判断类型,但是不是百分百准确的,比如如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了

function Person(){};
Person.prototype = {
  skill: function(){
    console.log('coding...');
  },
  city: "beijing"
}
const p1 = new Person();
console.log(p1.constructor === Person);
console.log(p1.constructor);
false
[Function: Object]

这是因为我们是以对象字面量{}来直接对原型进行赋值的,而之前是通过点操作符增加属性的,前者是完全覆盖,所以原型改变了,而{}Object()的简化方式,所以此时该原型的constructor就等于Object了,所以这里就是false



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