从 JS 中的构造函数返回 this

2023-12-31

如果我在 JavaScript 中有一个构造函数,我希望能够显式返回一些内容,以便在团队中工作时一切都清楚。

我读到,如果你在 JS 中使用函数作为构造函数,如果你返回任何内容,那么使用 new 关键字将是浪费精力。但我想知道你是否可以回来this来自构造函数并且安全,例如:

function MyConstructor(val){

      this.val = val;
      return this;   //attention here

}

var example = new MyConstructor(val);

这会产生期望的行为吗?


让我们从 JavaScript 的正常行为开始。如果您不从构造函数返回任何内容,它将按预期工作(当然)。

Hence

var Dog = function (name) {
  this.name = name;
};

var alice = new Dog('Alice');

结果是一个新对象,其name属性设置为Alice.

现在如果你尝试覆盖隐式会发生什么return通过显式调用声明构造函数吗?

我们来介绍一个return返回其他内容的语句:

var Dog = function (name) {
  this.name = name;
  return 23;
};

var alice = new Dog('Alice');

哪个值是alice现在?也许,你会期望它是23,但实际上并非如此。它仍然是一个带有name属性设置为Alice.

这里的问题是 JavaScript 比你更聪明:它看到你的return,但意识到您想要返回的内容的类型与使用该函数调用的事实不匹配new。因此return被忽略。

现在,如果我们尝试变得比 JavaScript 更聪明并返回类型匹配的东西(即对象)怎么办?

var Dog = function (name) {
  this.name = name;
  return { foo: 'bar' };
};

var alice = new Dog('Alice');

在这种情况下,JavaScript 认为您有充分的理由覆盖隐式return并实际使用你的。这意味着alice现在指向一个带有foo属性设置为'bar'.

所以,长话短说:如果你明确地调用

return this;

你最终会遇到最后一个案例。您覆盖隐式返回的对象。但由于您返回的实际上与隐式返回的相同,因此没有区别。

所以:是的,是一样的,但是调用return this;不需要。

一些开发人员使用此行为来欺骗 JavaScript 始终返回一个新对象,无论您是否调用构造函数new:

var Dog = function (name) {
  return {
    name: name
  };
};

var alice1 = new Dog('Alice');
var alice2 = Dog('Alice');

两个调用都会产生一个新对象name属性设置为Alice,但与前面的例子有一些不同:

  • 两个对象都只是对象字面量,其constructor属性未设置为Dog,他们都没有使用预期的原型链。
  • 在这种情况下with new实际上正在创建两个对象:一个是由new,另一个由您使用对象字面量语法。这意味着垃圾收集器需要做更多的工作。

因此,我认为您应该避免这种技术,要么正确使用构造函数,要么坚持使用工厂函数。

这与在中使用的效果相同@maboiteaspam 的回答 https://stackoverflow.com/a/30419791/1333873:

function DHT (opts) {
  var self = this
  if (!(self instanceof DHT)) return new DHT(opts)
  // ctor body
}

如果你用以下方式调用这个函数new, this被设置为一个对象,其constructor属性指向DHT功能。因此self instanceof DHT返回 true 并且运行实际的构造函数。

如果你调用这个函数时没有new, the if语句检测到这一点并运行它new自动为您提供(这至少比上述解决方案更好,最终会带来两个缺点)。

请注意,严格模式下不允许访问this来自未在对象上调用的函数,因此调用构造函数时无需new当您尝试访问时,关键字将导致错误this.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 JS 中的构造函数返回 this 的相关文章

  • 有没有办法将 Google 文档分割成多个 PDF?

    我想在 Google Scripts VBA 代码中复制我为 Word 文档编写的代码 基本上 它通过搜索我插入文档中的标签 将文档 切片 为多个 PDF 文件 目的是允许合唱团使用 forScore 管理乐谱的应用程序 在切片点插入先前注
  • Javascript 无法正确排序 DECIMAL 数字

    我有一些代码可以按字母顺序对名称进行排序 我遇到的问题是它处理小数的方式 它对名称进行排序 如下所示 我宁愿它按数字递增 DOG 1 0510 DOG 1 1031 DOG 11 1792 DOG 12 0920 DOG 12 1170 D
  • Javascript - 使数组索引 toLowerCase() 不起作用

    我试图将所有数组索引设置为小写字符串 但它不起作用 我在这里查看了其他答案并尝试了他们的解决方案 例如使用toString 添加之前toLowerCase但它不起作用 这很奇怪 我创建了一个问题的jsfiddlehere https jsf
  • “move(-1)”作为 AngularJS 表达式有什么问题吗?

    我收到此错误 parse ueoe Unexpected end of expression move 从这段代码来看
  • 使用 jquery 更改锚文本和图标

    我有一个隐藏或显示 div 的锚标记 但我无法更改它的文本和图标 如何更改文本和图标标签 因为目前它将图标标签解析为常规文本 锚标记 a class collapse info btn i class icon arrow up icon
  • 无法从 bash 脚本使用 nvm

    我正在尝试编写一个 shell 脚本来自动设置我的开发环境 安装 python nvm node mongo 等 我正在使用 nvm 来安装 Node js 它告诉您关闭并重新打开终端以开始使用 nmv 命令 我尝试获取 bashrc 和
  • Chrome 跨域 PATCH 请求不起作用

    我有一个带有 REST Api 的网站 现在我正在创建一个浏览器扩展 它将从某些页面收集数据并将它们发送回 REST Api 因为我希望我的扩展能够与 Firefox 和 Chrome 兼容 并且易于维护 所以我将实际代码作为脚本标记注入到
  • Webpack - 资产大小限制中的警告:以下资产超出了建议的大小限制 (244 KiB)

    当我在生产模式下运行 webpack 时 有资产规模限制 超出 的警告 我怎样才能运行而不出现这个错误 在我的项目中 我包含 css 并且我看到 webpack 构建中包含一些 node module 目录 但是如果我排除 css 的 no
  • 如何将OpenLayers多边形坐标转换为纬度和经度?

    我正在使用开放层 https openlayers org en latest examples draw freehand html绘制多边形并保存坐标的技术 这是我的代码 var raster new ol layer Tile sou
  • 如何获取 Spotify API 的访问令牌?

    我已经研究 Spotify api 和示例源代码几天了 但我仍然不知道如何获取访问令牌来访问用户的播放列表数据 我已经到达了拉起登录窗口 用户登录 然后收到授权码的地步 此时 我尝试做这样的事情 window open https acco
  • 如何在socket.io Nodejs服务器上列出房间

    在问题取得进展后如何创建socket io多播组 https stackoverflow com questions 6616922 how to create socket io multicast groups 6624604 6624
  • Lightbox:如何翻译“Image x of x”文本?

    我使用 Lightbox 2 作为图像集 当我的网站的访问者单击该集中的缩略图时 它将显示 图像的放大版本 下面是 描述 取自 a 标题属性 其下方 文本 Image x of x 例如 Image 1 of 12 有谁知道在哪里翻译 更改
  • Flask 和 Reactjs 抛出 JSX 转换错误

    我已经开始将 ReactJS 与 Python Flask 后端结合使用 通过 Flask 渲染模板时 我在 Chrome 控制台中收到以下客户端错误 错误 找不到模块 jstransform visitors es6 templates
  • 如何停止 PythonShell

    如何终止 停止 Node js 中 PythonShell 执行的 Python 脚本的执行 我在交互模式下运行 输出通过 socket io 发送到给定的房间 如果没有更多的客户端连接到这个房间 我想停止 python 脚本的执行 这是我
  • jQuery 模板插件:如何创建双向绑定?

    我开始使用 jQuery 模板插件 微软创建的 但现在我面临这个问题 模板用于绑定到对象数组的一堆表单 当我更改其中一个表单上的某些内容时 我希望更新绑定的对象 但我不知道如何自动执行该操作 这是一个简单的例子 现实生活中的模板和对象要复杂
  • IE9 中的无效字符 DOM 异常

    以下这段 JS 曾经在 IE8 中工作 现在在 IE9 中失败 document createElement 我收到以下异常 SCRIPT5022 DOM 异常 INVALID CHARACTER ERR 5 上面这段代码是不是不符合标准呢
  • redux - 如何存储和更新键/值对

    我正在使用 redux 和 React js 我想存储简单的键 值对 但无法获得正确的减速器语法 在这种情况下 每个键 值对将保持与外部系统的连接 这是正确的做法吗 我刚开始使用 redux 所以这有点神秘 export default s
  • 检测 html 选择框上的编程更改

    有没有办法让 HTML 选择元素在每次以编程方式更改其选择时调用函数 当使用 JavaScript 修改选择框中的当前选择时 IE 和 FF 都不会触发 onchange 此外 更改选择的 js 函数是框架的一部分 因此我无法更改它以在结束
  • javascript从字符串创建不区分大小写的正则表达式

    我试图通过以不区分大小写的方式将输入与正则表达式匹配来进行验证 正则表达式作为对象上的字符串从服务中下来 我可能会得到类似的东西 regex ane 我可以执行以下操作 var rx new RegExp object regex The
  • “memset”没有 DLL 那么如何 ctype 它

    如何使用memset在 jsc 类型中 没有对应的 DLL 我搜索 搜索了 js ctype 代码 但找不到要破解的示例 如果你只是想memset一个数组为零字节 然后我有 好消息 大家 js ctypes 会将新数组初始化为零 否则 最简

随机推荐