热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

你真的弄邃晓new了吗

良久没有写点东西了,总以为本身应当写点牛逼的,却又不知道怎样下笔。既然如此,照样回归最基本的吧,本日就来讲一说这个new。关于javascript的new关键字的内容上网搜一搜还真

良久没有写点东西了,总以为本身应当写点牛逼的,却又不知道怎样下笔。既然如此,照样回归最基本的吧,本日就来讲一说这个new。关于Javascript的new关键字的内容上网搜一搜还真不少,人人都说new干了3件事:

  • 建立一个空对象
  • 将空对象的__proto__指向组织函数的prototype
  • 运用空对象作为上下文挪用组织函数

笔墨比较难明,翻译成Javascript:

Javascriptfunction Base() {
this.str = "aa";
}
// new Base()干了下面的事
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

想一想是这么回事哈,那就连忙尝尝:

Javascriptvar b = new Base();
console.dir(b); // Base {str: 'aa', __proto__: Base}

彷佛是准确的,然则真的准确吗???

真的就3件事?

每一个对象都有一个constructor属性,那末我们来尝尝看new出来的实例的constructor是什么吧。

Javascriptconsole.dir(b.constructor); // [Function: Base]

可以看出实例b的constructor属性就是Base,那末我们可以猜想new是否是最少还做了第4件事:

Javascriptb.cOnstructor= Base;

以上效果看似准确,下面我们举行一点修正,这里我们修正掉原型的constructor属性:

JavascriptBase.prototype.cOnstructor= function Other(){ };
var b = new Base();
console.dir(b.constructor); // [Function: Other]

状况就不一样了,可以看出,之前的猜想是毛病的,第4件事应当是如许的:

Javascriptb.cOnstructor= Base.prototype.constructor;

这里犯了一个毛病,那就是没有邃晓好这个constructor的本质:当我们建立一个函数时,会自动天生对应的原型,这个原型包括一个constructor属性,运用new组织的实例,可以经由过程原型链查找到constructor。如下图所示:

《你真的弄邃晓 new 了吗》

这里非常感谢zonxin同砚指出我的毛病。

假如组织函数有返回值呢?

平常状况下组织函数没有返回值,然则我们照旧可以获得该对象的实例;假如组织函数有返回值,凭直觉来讲状况应当会不一样。我们关于之前的组织函数举行一点点修正:

Javascriptfunction Base() {
this.str = "aa";
return 1;
// return "a";
// return true;
}
var b = new Base();
console.dir(b); // { str: 'aa'}

我们在组织函数里设置的返回值彷佛没什么用,返回的照样本来对象的实例,换一些例子尝尝:

Javascriptfunction Base() {
this.str = "aa";
return [1];
// return {a:1};
}
var b = new Base();
console.dir(b); // [1] or {a: 1}

此时效果就不一样了,从上面的例子可以看出,假如组织函数返回的是原始值,那末这个返回值会被疏忽,假如返回的是对象,就会掩盖组织的实例

new最少做了4件事

总结一下,new最少做了4件事:

Javascript// new Base();
// 1.建立一个空对象 obj
var obj = {};
// 2.设置obj的__proto__为原型
obj.__proto__ = Base.prototype;
// 3.运用obj作为上下文挪用Base函数
var ret = Base.call(obj);
// 4.假如组织函数返回的是原始值,那末这个返回值会被疏忽,假如返回的是对象,就会掩盖组织的实例
if(typeof ret == 'object'){
return ret;
} else {
return obj;
}

new的不足

在《Javascript言语精炼》(Javascript: The Good Parts)中,道格拉斯以为应当防止运用new关键字:

If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning.

粗心是说在应当运用new的时刻假如忘了new关键字,会激发一些题目。最主要的题目就是影响了原型查找,原型查找是沿着__proto__举行的,而任何函数都是Function的实例,一旦没用运用new,你就会发明什么属性都查找不到了,由于相当于直接短路了。如下面例子所示,没有运用new来建立对象的话,就没法找到原型上的fa1属性了:

Javascriptfunction F(){ }
F.prototype.fa1 = "fa1";
console.log(F.fa1); // undefined
console.log(new F().fa1); // fa1

这里我合营一张图来讲明个中道理,黄色的线为原型链,运用new组织的对象可以一般查找到属性fa1,没有运用new则完整走向了别的一条查找途径:

《你真的弄邃晓 new 了吗》

以上的题目关于有继承的状况表现得更加显著,沿着原型链的要领和属性全都找不到,你能运用的只要短路以后的Function.prototype的属性和要领了。

固然了,忘记运用任何关键字都邑引发一系列的题目。再退一步说,这个题目是完整可以防止的:

Javascriptfunction foo()
{
// 假如忘了运用关键字,这一步骤会悄然帮你修复这个题目
if ( !(this instanceof foo) )
return new foo();
// 组织函数的逻辑继承……
}

可以看出new并非一个很好的实践,道格拉斯将这个题目形貌为:

This indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of Javascript. Javascript’s constructor pattern did not appeal to the classical crowd. It also obscured Javascript’s true prototypal nature. As a result, there are very few programmers who know how to use the language effectively.

简朴来讲,Javascript是一种prototypical范例言语,在建立之初,是为了投合市场的须要,让人们以为它和Java是相似的,才引入了new关键字。Javascript本应经由过程它的Prototypical特征来完成实例化和继承,但new关键字让它变得不三不四。

再说一点关于constructor的

虽然运用new建立新对象的时刻用议论了这个constructor属性,然则这个属性好像并没有什么用,或许设置这个属性就是一种习气,可以让其他人直观邃晓对象之间的关联。

欢迎光临小弟博客:Superlin’s Blog
我的博客原文:你真的弄邃晓new了吗

参考

  • 再谈Javascript面向对象编程
  • Javascript的实例化与继承:请停止运用new关键字

推荐阅读
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了作者在开发过程中遇到的问题,即播放框架内容安全策略设置不起作用的错误。作者通过使用编译时依赖注入的方式解决了这个问题,并分享了解决方案。文章详细描述了问题的出现情况、错误输出内容以及解决方案的具体步骤。如果你也遇到了类似的问题,本文可能对你有一定的参考价值。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有