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

 更新时间:2021年05月13日 11:05:34   作者:恪愚  
众所周知JS中new的作用是通过构造函数来创建一个实例对象,这篇文章主要给大家介绍了关于JavaScript中实现new的两种方式引发的相关资料,需要的朋友们下面随着小编来一起学习学习吧

前言

当你 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

test1

可以看到,以 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

test2

到这里,我似乎明白了什么,又似乎没明白…

我决定这么做:

let b=new Best();
console.log(b);

test3

console.log(Best.prototype);

test4

恍然大悟!

原来我们平时说的 “当读取实例属性时,如果找不到,就会查找与对象关联的原型中的属性;如果还找不到,就去找原型的原型,直到最顶层(__proto__ 为null)为止” 是指 “一直顺着 __proto__ 向上查找”(注意:不经过prototype!)。

__proto__prototype 之间又有什么呢?

console.log(b.__proto__);
console.log(Best.prototype);

test5

哦!这就是我们常听到的“实例的 __proto__ 等于对象的 prototype ”吧。

那现在回过头来,打印一下 o2 这个对象:

console.log(o2);

test6

你有没有想到什么?

根据上面所描述的那样,o2 就是 Best 的实例啊!

所以说,create() 函数实际上返回了一个对象的实例?

但 o1 仍然“不为所动”!

test7

所以我们能否猜测:在 Object.create() 函数中应该是拿到对象的原型并以实例的形式返回:

Object.create=function(o){
	let F=function(){};
	F.prototype=o;
	return new F();
}

为什么这里要用函数再 new 的方式?而不是直接用对象去接收?

test8

这和“为什么vue中data是一个函数而不是直接的对象”其实是一个问题:JavaScript中的对象是引用类型,在一个实例中改变某一个元素的值其余实例的值都会发生改变!

而通过create函数则不会:

test8

总结

到此这篇关于JavaScript中实现new的两种方式的文章就介绍到这了,更多相关JS实现new的方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中的值是按值传递还是按引用传递问题探讨

    JavaScript中的值是按值传递还是按引用传递问题探讨

    这篇文章主要介绍了JavaScript中的值是按值传递还是按引用传递问题探讨,本文讲解了按值传递、按引用传递、按共享传递、基本类型的不可变(immutable)性质等内容,需要的朋友可以参考下
    2015-01-01
  • JavaScript暂停和继续定时器的实现方法

    JavaScript暂停和继续定时器的实现方法

    这篇文章主要介绍了JavaScript暂停和继续定时器的方法的相关资料,非常不错,需要的朋友可以参考下
    2016-07-07
  • javascript实现动态显示颜色块的报表效果

    javascript实现动态显示颜色块的报表效果

    本文主要介绍了javascript实现动态显示颜色块的报表效果的相关知识。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-04-04
  • JavaScript实现tab栏切换的几种常用方法

    JavaScript实现tab栏切换的几种常用方法

    这篇文章主要给大家介绍了关于JavaScript实现tab栏切换的几种常用方法,在Web开发中Tab切换是一个常见的功能,它允许用户在不同的页面部分之间进行切换,需要的朋友可以参考下
    2023-12-12
  • js DOM模型操作

    js DOM模型操作

    文档对象模型DOM(Document Object Module)定义了用户操作文档对象的接口,它使得用户对HTML有了空前的访问能力,并使开发者能将HTML作为XML文档来处理。
    2009-12-12
  • 深入浅析JS是按值传递还是按引用传递(推荐)

    深入浅析JS是按值传递还是按引用传递(推荐)

    这篇文章主要介绍了JS是按值传递还是按引用传递(推荐)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • 第一次接触神奇的Bootstrap表单

    第一次接触神奇的Bootstrap表单

    第一次接触神奇的Bootstrap表单,Bootstrap让Web开发更迅速、更简单,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • uni-app中onBackPress()监听页面返回(更新数据)

    uni-app中onBackPress()监听页面返回(更新数据)

    这篇文章主要给大家介绍了关于uni-app中onBackPress()监听页面返回(更新数据)的相关资料,在UniApp中,可以通过监听页面刷新的生命周期函数来监听页面的返回,然后重新调用接口进行刷新,需要的朋友可以参考下
    2023-10-10
  • javascript实现blob加密视频源地址的方法

    javascript实现blob加密视频源地址的方法

    这篇文章主要介绍了javascript实现blob加密视频源地址的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • JavaScript从数组中删除特定数据的方法总结

    JavaScript从数组中删除特定数据的方法总结

    js数组是js部分非常重要的知识,有时我们有这么个需求js数组删除指定元素,下面这篇文章主要给大家介绍了关于JavaScript从数组中删除特定数据的相关资料,需要的朋友可以参考下
    2022-08-08

最新评论