原型链prototype、__proto、constructor的那些问题整理

再了解原型链之前,我们先来看看构造函数和实例对象的打印结构

- 函数

这里我们定义一个构造函数Fn,然后打印它的结构吧

复制代码
function Fn(){}
console.dir(Fn)

控制台得到结构

从上面结构我们能看的出来,函数有两种原型,一种是作为函数特有的原型:prototype,另一种是作为对象的__proto__类型(就是上图那个[[Prototype]],__proto__是浏览器自己填充的,新浏览器都能看到,我的浏览器版本低,还看不到哈,先这么写)

我们先来看做为函数特有属性的prototype哈,我们展开看看

可以看到函数的prototype上有一个构造函数constructor和一个__proto__属性,这个constructor实际上就是函数本身,另外一个__proto__呢,你看它的值是一个对象Object呢.也就是说函数的prototype的__proto__指向Object的prototype,我们下面运行看看是不是这样呢?

复制代码
Fn.prototype.__proto__ === Object.prototype.    // true

我们运行结果果然和预期一样返回了true.

我们再来看函数的另外一个原型__proto__,我们展开它

我们看到函数的__proto__是一个Function,我们猜想这个函数的__proto__指向Function的prototype,我们来运行看看

Fn.proto === Function.prototype. // true

果然,和预期一样,所以我们根据上面的一些结果有了总结

1、函数(箭头函数除外,箭头函数没有prototype属性哈)有两个原型,一个是作为函数特有的prototype,另一个是作为对象的__proto__

2、函数的 prototype中constructor就是函数本身

3、函数的 prototype中__proto__属性指向Object的prototype

4、函数的__proto__指向Function的prototype

  • 对象

现在我们根据上面的构造函数,我们实例化一个对象来看看结构

复制代码
let obj = new Fn()
console.dir(obj)

我们来看看obj对象的结构

可以看到上面的obj对象只有一个__proto__原型,我们展开看似乎和它的构造函数的prototype长的一样呢,我们运行看看

obj.proto === Fn.prototype. // true

果然,结果和我们预期一样

所以我们有了结论:

对象只有一条__proto__原型,并且对象的原型__proto__就指向构造函数的prototype

  • constrctor

我们再回过头来看刚刚构造函数中那个constrctor,上面你看实例对象obj可以找到构造函数的prototype,而这个prototype上就有constrctor,所以由此得出根据构造函数实例得到的每一个实例对象,都能找到它的构造函数

我们来运行看看哈

复制代码
 obj.__proto__.constructor    // ƒ Fn(){}

没有问题,和预期一样,这么看,我们现在就可以把上面写法精简一下,因为对象上的属性和方法,自己上面没有,就会去它的原型链上面去找,也就是对象会有原型的继承

根据这个原则,我们把上面运行的就能精简一下了

复制代码
obj.constructor.   //. ƒ Fn(){}

我们就这样就找到了构造函数了.

这里找到构造函数的目的是啥呢,除了用它来实例化对象之外,还能给原型链添加公共的属性和方法,供所有的实例对象调用.

我们来看一段代码

复制代码
obj.constructor.prototype.sayHello = function(){ console.log("hello")}
obj.sayHello().  // hello
let obj2 = new obj.constructor()
obj2.sayHello(). // hello

从上得出,我们可以通过constructor的prototype添加通用的属性和方法.

有人提出干嘛那么麻烦,我们通过对象的__proto__直接添加属性和方法不是更好嘛,代码更精简,我们来看看

obj.proto .name = "zhang"

obj.name. // "zhang"

obj.name // "zhang"

我们看到我们通过对象的__proto__也能添加构造函数的公用属性和方法,所以,这样写到底有没有问题呢?

其实这样写虽然在浏览器运行没有问题,但是上面我们提到过,__proto__这个属性是浏览器厂商自己内置的,有的浏览器是不支持的,所以使用constructor更可靠一点。

就先整理到这里

相关推荐
Python×CATIA工业智造25 分钟前
Frida RPC高级应用:动态模拟执行Android so文件实战指南
开发语言·python·pycharm
我叫小白菜1 小时前
【Java_EE】单例模式、阻塞队列、线程池、定时器
java·开发语言
狐凄1 小时前
Python实例题:基于 Python 的简单聊天机器人
开发语言·python
weixin_446122462 小时前
JAVA内存区域划分
java·开发语言·redis
悦悦子a啊3 小时前
Python之--基本知识
开发语言·前端·python
QuantumStack3 小时前
【C++ 真题】P1104 生日
开发语言·c++·算法
whoarethenext4 小时前
使用 C++/OpenCV 和 MFCC 构建双重认证智能门禁系统
开发语言·c++·opencv·mfcc
OEC小胖胖4 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水4 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
代码的奴隶(艾伦·耶格尔)4 小时前
后端快捷代码
java·开发语言