理解原型链中的__proto__与prototype

本文深入探讨JavaScript中的__proto__与prototype的区别,解析原型链的工作机制,包括构造函数、实例对象及继承路径。并通过实例说明如何利用这些概念进行对象继承。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

前面发了一篇关于深入理解js的继承机制的文章,入口如下:

【转】彻底理解js中关于prototype的继承机制

在js的继承机制中,prototype对象有着至关重要的作用。笔者在此从原型链的角度,聊聊__proto__和prototype。

__proto__与prototype的区别

原型链是一个耳熟能详的词儿,它代表着js对象的“族谱”。一个对象的原型链展示了一条完整的继承路径。

在原型链中,__proto__与prototype起着承上启下的作用。虽然两者长得很像,但还是有本质区别的。

  • js中每个对象都具有内置属性__proto__,该属性的值就是该对象构造函数的prototype对象。对象字面量的__proto__的值就是Object.prototype。
  • js中并不是所有的对象都有内置属性prototype。因为js中函数可以充当构造函数,所有只有函数才有prototype属性。当然函数也是对象,所以函数也有内置的__proto__属性。只不过只有拿函数当作构造函数来使用时,才需要我们去关注__proto__和prototype属性。
  • 构造函数构造出实例对象后,实例对象默认是继承prototype对象中的属性和方法的。具体内部是怎样实现继承的呢?实例通过设置自己的__proto__指向承构造函数的prototype来实现这种继承。
  • 一般情况下是不推荐直接操作对象的内置属性__proto__的。而prototype却没有这种限制,可以进行修改调整,实现继承的扩展。

原型链图解

所谓一图胜千言,先来看下原型链的一张图解,概括的很详尽。

从图中可以看出,在原型链中,对象的__proto__属性可以理解为“穿针引线”,而链中的每个节点则是构造函数的prototype对象,prototype对象中定义了需要被继承的属性和方法。

instanceof运算符

instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例。

f1 instanceof Foo; // true
f1 instanceof Object; // true

看上面原型链图中的实例对象f1,结合上面代码的运行结果,可以看出instanceof运算符,实际是沿着指定实例对象的原型链在查找指定构造函数的prototype对象,如果存在该prototype对象则返回true,否则返回false。

鸡和蛋的问题

众所周知,js是单继承的。从原型链图中可以看出,任何一个对象的原型链顶端一定是Object.prototype,而Object.prototype之上就是null啦。

Function instanceof Object; // true

js中,万物皆对象。Function作为构造函数时,Function.prototype通过__proto__指向了顶端的Object.prototype,所以上面的运行结果表明Function继承于Object。

Object instanceof Function; // true

看到这里很多人会迷惑了,到底是Object继承了Function,还是Function继承了Object呢?这个就好比先有的鸡还是先有的蛋呢?

笔者认为,通过上图中的原型链说明,毋庸置疑的是Object.prototype位于链的顶端。只不过函数在js中太特别了,Object可以作为构造函数存在,而所有函数(包括构造函数)均是通过Function构造函数产生的实例对象,所以Object构造函数的__proto__指向的是Function.prototype,也就产生了上面的运行结果。

从原型链图中也可以发现,Function作为构造函数,Function.__proto__指向的是Function.prototype,而Function的prototype对象也是Function.prototype,这点是非常特殊的存在。

Object.create方法

Object.create方法允许不通过构造函数产生一个实例对象,产生的实例对象继承于指定的另一个实例对象,看下面的代码原理。

if (typeof Object.create !== 'function') {
  Object.create = function (obj) {
    function F() {}
    F.prototype = obj;
    return new F();
  };
}

可以看出,Object.create方法产生的实例对象,其__proto__指向指定的obj,obj中的属性和方法可以供产生的实例对象继承。

参考文章

从__proto__和prototype来深入理解JS对象和原型链

转载于:https://my.oschina.net/angerbaby/blog/2994445

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值