WD1X.COM - 问答一下,轻松解决,电脑应用解决专家
主板显卡CPU内存显示器
硬盘维修显卡维修显示器维修
注册表系统命令DOS命令Win8
存储光存储鼠标键盘
内存维修打印机维修
WinXPWin7Win11Linux
硬件综合机箱电源散热器手机数码
主板维修CPU维修键盘鼠标维修
Word教程Excel教程PowerPointWPS
网络工具系统工具图像工具
数据库javascript服务器
PHP教程CSS教程XML教程

由两种实现new的方式引发的探究

更新时间:2021-05-06 16:32 作者:恪愚点击:
当你 new 一个构造函数时发生了什么?
“众所周知”的三步:
 
创建一个空对象,将它的引用赋给 this,继承函数的原型;
通过 this 将属性和方法添加至这个对象;
最后返回 this 指向的新对象,也就是实例。
一般来说在js中大概是这样的:
 
function Mynew(parent,...rest){
let obj={};
obj.__proto__=parent.prototype;
let res=parent.apply(obj,rest);
return typeof res=="object"?res:obj;
}
 
上面提到的“空对象”只是简称。事实上,就算是定义一个 {} ,它也会从 Object.prototype 上继承很多方法和属性。
《JavaScript语言精髓与编程实践》中提出了一个“更加空白的对象”:它有两种情况 —— Constructor.prototype 值为null;或者Object.getPrototypeOf(obj) 值为null。
 
但通常我们还能见到另一种写法:
 
function Mynew_2(parent,...rest){
let child=Object.create(parent.prototype);
let result=parent.apply(child,rest);
return typeof result=="object"?result:child;
}
 
这两种实现的不同无疑引起了我的兴趣!
 
Object.create()是怎么实现的?
我们来看一段代码:
 
var Best1=function(){
this.a=2;
}
var o1=Object.create(Best1);
var o2=Object.create(Best1.prototype);
console.log(o1.a); // undefined
console.log(o2.a); // undefined
 
 
可以看到,以 o1 为例,Object.create() 失去了对原来对象属性的访问,而 o2 …同理。
 
再来看另一段代码:
 
var Best=function(){
this.a=2;
}
Best.prototype.a=3;
var o1=Object.create(Best);
var o2=Object.create(Best.prototype);
console.log(o1.a); // undefined
console.log(o2.a); // 3
 
到这里,我似乎明白了什么,又似乎没明白…
 
我决定这么做:
 
let b=new Best();
console.log(b);
 
 
console.log(Best.prototype);
 
 
恍然大悟!
原来我们平时说的 “当读取实例属性时,如果找不到,就会查找与对象关联的原型中的属性;如果还找不到,就去找原型的原型,直到最顶层(__proto__ 为null)为止” 是指 “一直顺着 __proto__ 向上查找”(注意:不经过prototype!)。
 
! 那 __proto__ 和 prototype 之间又有什么呢?
 
console.log(b.__proto__);
console.log(Best.prototype);
 
哦!这就是我们常听到的“实例的 __proto__ 等于对象的 prototype ”吧。
 
那现在回过头来,打印一下 o2 这个对象:
 
console.log(o2);
 
 
你有没有想到什么?
根据上面所描述的那样,o2 就是 Best 的实例啊!
 
所以说,create() 函数实际上返回了一个对象的实例?
 
但 o1 仍然“不为所动”!
 
所以我们能否猜测:在 Object.create() 函数中应该是拿到对象的原型并以实例的形式返回:
 
Object.create=function(o){
let F=function(){};
F.prototype=o;
return new F();
}
 
为什么这里要用函数再 new 的方式?而不是直接用对象去接收?
 
这和“为什么vue中data是一个函数而不是直接的对象”其实是一个问题:JavaScript中的对象是引用类型,在一个实例中改变某一个元素的值其余实例的值都会发生改变!
 
而通过create函数则不会:
 
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
你可能感兴趣的内容