new、原型和原型链浅析

new、原型和原型链

继承是编程里的一个常见思想。通过对父对象属性、方法的继承子对象可以不用编写相同的代码但能调用对应的属性、方法。

js通过原型来实现继承特性。

原型

在js中,在js中每一个对象都有一个自己的"父对象",这个"父对象"就叫做原型。

了解原型我们需要知道三个属性以及他们对应的含义

  • __ proto__ :对象的一个属性,指向这个对象的原型。
  • prototype :函数的独有属性,指向这个函数的原型。
  • constructor:对象的一个函数,指向这个对象的构造函数。

这里需要特别提到的有两点。

1、__ proto__在ES标准定义里的属性名应该是\[prototype],具体实现是由浏览器代理自己实现。不同的浏览器可能在实现\[prototype]上命名不同,功能是一致的。本文采用谷歌浏览器的实现命名方式__ proto__。

2、prototype是函数特有的属性,对象变量并没有prototype属性指向原型。但是由于函数也是一种对象,所以函数既有prototype,又有__ proto__,还有指向构造函数的constructor属性。

javascript 复制代码
let func = function(value){
    this.value = value
}

func.prototype.getValue = function() {
  return this.value;
}

let objA = new func(4);

这段代码是一个简单的通过new关键字将func函数作为构造函数来实例化一个对象objA

func()是一个构造函数,它有着特殊的属性prototype,在js中函数也是对象,所以它也有__ proto__constructorprototype__ proto__都指向原型func.prototype。 constructor指向func()的构造函数,这个在之后的原型链部分再讲。

func.prototype是一个原型对象,它也有__ proto__constructor。在js中一个构造函数的它的constructor指向构造函数

objA作为对象他有两个元素,__ proto__constructorconstructor指向构造函数func(), __ proto__指向原型。由于new关键字在实例化对象时是将构造函数的原型赋给实例化对象,所以__ proto__指向的是func.prototype。

func的prototype和objA的__ proto__都指向func.prototype,objAfunc.prototype的构造函数(constructor)都是func

new

通过new关键字调用一个函数时,将其视为一个构造函数,创建一个该构造函数的实例对象。这个对象拥有这个函数的共享属性、共享方法。具体实现在这里先不展示,需要知道的是: 在实例化这个对象的过程中,new将构造函数的prototype赋给了实例对象。

所以实例对象和构造函数实际上是共享一个原型。

原型链

对象有原型和构造函数,原型对象和构造函数也不例外。它们都有自己的原型和构造函数。 调用一个对象没有的方法时,该对象就会查找它的原型\[prototype]查看是否有该方法,如果它的原型也没有该方法就会查找它原型的原型,直到查到Object.prototype。因为Object.prototype的原型是null。

这个通过\[prototype]将各个原型穿起来链接就叫原型链。

如图所示从上到下分层来进行对这个原型链的解析。

第一层: ObjA是func()实例化对象,所以func()是ObjA的构造函数。在js内部,每个函数都是由Function()实例化而来所以Function()是fun()的构造函数。这里需要注意一点,其实ObjA自身是没有constructor属性的,在查询constructor属性时是遍历到自身的原型然后调用的原型的constructor。

所以实例对象的constructor == 实例对象的原型的constructor

Function()函数比较特殊,它自己就是自己的构造函数。

第二层:objA在实例化时func()将自身的原型赋给了它,所以objA和func()是同一原型。 由于ObjA是对象。所以只有__ proto__属性指向func.prototype。

每个构造函数在创建时,它的原型的constructor会自动指向它本身。 所以func.prototype.constructor == func。

同样Function.prototype.constructor指向Function()

第三层:由于fun.prototype是一个对象且它不是由其它构造函数构造得来,所以它的原型是Object.prototype,func.prototype.__ proto__ == Object.prototype。

Function.prototype作为一个Function()的原型对象,自然它的原型也指向Object.prototype,Function.prototype.__ proto__ == Object.prototype。

Object()是Object的构造函数,所以Object().prototype.constructor == Object()

第四层:Object()作为最上层的对象,所有的对象都是从Object.prototype直接或间接继承而来。所以Object()再往上没有原型。 Object.prototype == null

补充一下:

\[prototype]可以通过Object.setPrototypeOf修改构造函数的原型,但是不建议这么做,因为构造函数在修改原型时不会一同修改

javascript 复制代码
let func = function(value){
   this.value = value
}

func.prototype.getValue = function() {
 return this.value;
}

let objA = new func(4);
console.log(objA.value)

let o = function(value){
   this.value = value + 1
}

Object.setPrototypeOf(func.prototype, o.prototype)

let objB = new func(2);
console.log(objB.value)
相关推荐
小林ixn26 分钟前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧2 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展
窝子面3 小时前
手搓最简前后端协作-node
javascript·数据库
qetfw3 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具
甲维斯3 小时前
我要开始吹牛逼了!Kimi K3 “宇宙无敌”!
前端·人工智能
a1117763 小时前
微光小屋-前端养成小游戏 开源项目
前端
kyriewen4 小时前
我让AI给前端项目做了一次完整的Code Review——它和人类的差距,比我想的大得多
前端·javascript·ai编程
张鑫旭4 小时前
快速过下我2026年上半年的前端学了些啥
前端