资讯专栏INFORMATION COLUMN

为什么都说js 里面任何对象最终都继承了Object对象

Gemini / 520人阅读

摘要:今天闲来无事,看见几行小字。又说所有对象,继承终是。强行押韵一波这首诗的意思就是说的我今天没有什么事情,然后无意中又在网上看到了任何对象都是从对象继承而来的这句话。一时兴起,便去验证这句话。

今天闲来无事,看见几行小字。
又说所有对象,继承终是Obj。
—— 强行押韵一波

这首诗的意思就是说的我今天没有什么事情,然后无意中又在网上看到了“任何对象都是从Object对象继承而来的”这句话。一时兴起,便去验证这句话。ps. 我好像从来在原型链上面都没有走到过Object对象,我今天一定要把它点出来!

首先我们探究ES5、ES6里面的__proto__、prototype

首先我们从《JavaScript高级程序(第三版)》里面找到这张图

此图片告诉了我们2个道理:

1、一个实例的 [[Prototype]] (__proto__属性),指向它构造函数的原型对象
这句话听起来有点儿复杂,把它简化一下
一个实例的__proto__属性,指向它的原型对象
2、一个原型对象的constructor属性又指回了这个对象

下面我们来console一下ES5构造函数和ES6类的__proto__、prototype
1、es5 和 es6 这两个实例的__proto__ 指向了它们构造函数的原型对象(简称指向了它们的原型对象)

function ES5Fun(language){
  this.name = "ES6Class类";
  this.language = language;
}
ES5Fun.prototype.favorit = "足球";
let es5 = new ES5Fun("中文");


class ES6Class {
  constructor(props){
    this.className = "ES6Class类"
  }
  printfName(){
    console.log("现在printName准备开始打印")
    this.getName();
  }
  getName(){
    console.log("此类的类名是:" +this.className)
  }
}
let es6 = new ES6Class();


console.log(ES5Fun.prototype)
console.log(ES6Class.prototype)

在chrome中的运行结果为:

console.log(es5.__proto__ === ES5Fun.prototype)            //true
console.log(es6.__proto__ === ES6Class.prototype)          //true

2、es5 和 es6 这两个实例的constructor 指向了它们的构造函数

//这是Node 里面运行的结果
console.log(es5.constructor)        //[Function: ES5Fun]
console.log(es6.constructor)        //[Function: ES6Class]
console.log(es5.constructor === ES5Fun)            //true
console.log(es6.constructor === ES6Class)          //true

3、构造函数ES5Fun 和 ES6Class 的原型对象的 constructor 又指回了它们本身

//这是Node 里面的运行结果
console.log(ES5Fun.prototype.constructor)                //[Function: ES5Fun]        
console.log(ES6Class.prototype.constructor)              //[Function: ES6Class]  
console.log(ES5Fun === ES5Fun.prototype.constructor)                //true
console.log(ES6Class === ES6Class.prototype.constructor)            //true

所以推导出

console.log(es5.constructor === ES5Fun.prototype.constructor)                //true
console.log(es6.constructor === ES6Class.prototype.constructor)              //true
console.log(es5.constructor === es5.__proto__.constructor)                   //true 
console.log(es6.constructor === es6.__proto__.constructor)                   //true   

下面我要开始开车了
准备好了吗?嘟嘟,嘟嘟。嘟嘟,嘟嘟。

ES5Fun 和 ES6Class 继续再往它们的构造函数和原型对象上面延伸看能得到什么

首先打印出Function对象本身,看看是什么便于后面参考

//Node 下面的执行结果
console.log(Function)        //[Function: Function]

ES6Class的构造函数是 Function对象

//Node 下面的执行结果
console.log(ES6Class.constructor)          //[Function: Function]
console.log(ES6Class.constructor === Function)           //true

ES6Class的__proto__ 当然也就指向它构造函数的原型对象

console.log(ES6Class.__proto__)        //[Function]
console.log(ES6Class.__proto__ === Function.prototype)        //true

那么Function的construct属性呢? 神奇的事情出现了,Function的construct属性竟然就等于 ES6Class的constructor属性

console.log(Function.constructor);
console.log(Function.constructor === ES6Class.constructor)

原因是Function的constructor 没有指向它的构造函数而是指向了它本身(或者说Function的构造函数就是它本身)

console.log(Function.constructor === Function)        //true
console.log(Function.constructor.constructor.constructor.constructor.constructor.constructor.constructor.constructor)        //[Function: Function]
console.log(Function.constructor === Function.constructor.constructor.constructor.constructor.constructor.constructor)       //true 

Function的原型对象等于 ES6Class.__proto__

console.log(Function.__proto__)                //[Function]
console.log(Function.__proto__ === ES6Class.__proto__)        //true
// 再次证明 Function.constructor 指向它自己
console.log(Function.constructor.__proto__)    //[Function]
console.log(Function.constructor.constructor.constructor.constructor.__proto__)        //[Function]

一个对象的原型对象的constructor 指向这个对象自己,这一点儿Function也不例外

console.log(Function.__proto__.constructor);                //[Function: Function]
console.log(Function.__proto__.constructor === Function);            //true

最后我们终于找到了原型链的尽头 Function原型对象的原型对象是一个{ }

console.log(Function.__proto__.__proto__)        //{}
//它再往上的原型对象是一个null
console.log(Function.__proto__.__proto__.__proto__)        //null
//这个原型对象的constructor指向了Object
console.log(Function.__proto__.__proto__.constructor)      //[Function: Object]
console.log(Function.__proto__.__proto__.constructor === Object)        //true
总结

1、Function.constructor 指向它本身,不指向它的构造函数(或者说Function的构造函数就是它本身)这个我也不太清楚
2、Function.__proto__.__proto__.constructor === Object

console了这么多东西,我先去厕所吐了,兄弟们点个赞再走

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106249.html

相关文章

  • 说说Prototypal Inheritance

    摘要:因为是一种长程的关联,基类的修改对继承者的影响难以估计和维护,具有特性,因此从耦合度的角度说,它大大提高了组件的耦合度,高耦合度不是罪过,但它应对变化的能力变差了。 JavaScript开发者的繁殖速度和它的语言特性一样迅猛,这是好事,但是也把JS搞得比任何一种其他语言都更像流行乐,充满教派和玄学。但编程不是玄学,是科学和工程。这篇文章就用来阐述和探讨JavaScript中的一个比较关...

    jzzlee 评论0 收藏0
  • 深度剖析js原型及面向对象

    摘要:返回一个对象先说一个最常用的方法构造函数获取所有节点获取节点的长度作用于链式调用测试上面的代码就可以实现的效果因为我没读过源码。 es5版本:(过两天写es6 版本的)由浅入深地讲,先说使用, function person(age, sex) { this.age = age; this.sex = sex; this.clothes ...

    Corwien 评论0 收藏0
  • JavaScript即学即用教程[1]-类型系统

    摘要:如图反而,由于这些的都是继承自,所以原型链拐向了。因此这样一个实例,他顺着原型链是找到了如图选学内容如果我们刨根问底,去寻找和的根源的话,那这个问题又稍微有点复杂了。 基本类型 Number, Boolean, String, null, undefined 什么样的变量是 undefined 声明了变量却没赋值 未声明的变量 包装类型 其实js里面也有像java,c#里所谓的包装...

    toddmark 评论0 收藏0
  • Mobx 源码阅读简记

    摘要:源码简记整体会写得比较乱,同时也比较简单,和读书笔记差不多,基本是边读边写。见谅主要三大部分的原子类,能够被观察和通知变化,继承于。同时里面有几个比较重要的属性与方法。 Mobx 源码简记 整体会写得比较乱,同时也比较简单,和读书笔记差不多,基本是边读边写。见谅~ 主要三大部分Atom、Observable、Derivation Atom Mobx的原子类,能够被观察和通知变化,obs...

    paulli3 评论0 收藏0
  • JS 兼容、继承、bind、this

    摘要:我们都说构造函数开头首字母大写但那只是人为的规定并不是语法。只是一个操作符,任何函数都能通过来执行,并不只是构造函数,只不过我们认为之后的都是构造函数。 这一篇文章主要是讲述一些有关js的小知识点。因为我也不是很精通哪一方面只能把自己知道的一点点写出来。取名大杂烩也是这意思吧,既然是道菜那么就来尝尝我的手艺吧。 第一道菜 1.首先,我想说一下事件绑定。事件绑定我们都知道有:on + t...

    YacaToy 评论0 收藏0

发表评论

0条评论

Gemini

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<