今天闲来无事,看见几行小字。
又说所有对象,继承终是 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 了这么多东西,我先去厕所吐了,兄弟们点个赞再走