帮助理解 javascript 全局消除技术

2023-12-26

来自 DailyJS“让我们构建一个 JavaScript 框架” http://dailyjs.com/2010/02/25/djscript-part-1-structure/我不太确定以下代码,显然用作全局抑制技术。

到目前为止,我的理解对 (function(){}) 犹豫不决。我理解设置图灵变量,将 global.turing 设置为图灵,并返回 window 或 this (如果不在浏览器中),但是 (function(global){})(this 或 window) 的事情让我感到困惑......我见过类似的东西

var mything = {}并将所有代码设置为神话,但这个习惯用法让我有点困惑。

我真的很想理解这里的推理,而不是记住它“有效”

(function(global) {
  var turing = {
    VERSION: '0.0.1',
    lesson: 'Part 1: Library Architecture'
  };

  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
})(typeof window === 'undefined' ? this : window);

(这个答案已有 4 年多了(截至 2015 年 4 月),虽然它仍然正确,但我认为它需要一个更一般的解释 - 见下文)

原答案

想一想:

(function (x) {
    // ...
})(y);

as:

function functionName(x) {
    // ...
}
functionName(y);

但不需要给它一个名称(如 functionName)。

So this:

(function(global) {
    // ...
})(typeof window === 'undefined' ? this : window);

真的只是:

function functionName(global) {
    // ...
}
functionName(typeof window === 'undefined' ? this : window);

它是一个只有一个参数的函数(称为global在函数内)并调用它typeof window === 'undefined' ? this : window这意味着相同:

function functionName(global) {
    // ...
}
if (typeof window === 'undefined') {
    functionName(this);
} else {
    functionName(window);
}

但使用更短的符号(并且不命名函数)。

更一般的解释

我在 4 年前写了这个答案,我认为是时候对这里涉及的概念添加一些更一般的解释了。

正如我上面所解释的,这个:

(function (x) {
    // ...
})(y);

是这个的匿名版本:

function functionName(x) {
    // ...
}
functionName(y);

其中(如果只调用一次)是usually(例外情况见下文)也与此相同:

function functionName() {
    var x = y;
    // ...
}
functionName();

回到匿名立即调用函数,如下:

(function (x) {
    // ...
})(y);

与此相同:

(function () {
    var x = y;
    // ...
})();

这对大多数人来说可能有更明显的意义。 (这里立即调用的函数没有参数,仅用于为变量和其他嵌套函数提供一个隔离的作用域,这样我们就不会污染外部或全局作用域 - 这也是在中使用参数的主要原因首先立即调用匿名函数。)

在括号上

顺便说一下,这个:

(function () {
    // ...
})();

与此相同:

(function () {
    // ...
}());

由于语言歧义,函数周围需要括号,但它们可能包括()实际上调用该函数,也可能不调用该函数 - 尽管有些人认为这里的第二种形式看起来更清晰。看道格拉斯·克罗克福德 (Douglas Crockford) 的解释 https://youtu.be/taaEzHI9xyY?t=33m39s了解更多细节以及为什么他认为第一个版本看起来像“狗球”。

例外情况

之前我说过这样的:

(function (x) {
    // ...
}(y));

与此相同:

(function () {
    var x = y;
    // ...
}());

大多数情况下,对于一个参数来说这是正确的(这不会在同时依赖于其值的同时屏蔽外部作用域中的同名变量),并且对于多个参数来说通常是正确的(如果它们不这样做)也相互依赖)。我希望通过示例可以更加清楚。

当我们有这段代码时:

(function (x) {
    // ...
}(x + 1));

那么我们不能将其翻译为:

(function () {
    var x = x + 1;
    // ...
}());

因为在第一个版本中我们添加 1outer x并将结果绑定到inner x一旦我们进入函数内部,我们就只有内部的了x与(甚至是新的let https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let声明对我们没有帮助)。

另一个例子:

(function (x, outer_x) {
    // ...
}(1, x));

在这里你可以设置old_x的值x从外部范围和x在内部范围中将其设置为新值 1,并且您不必担心顺序。但如果你这样做了:

Summary

正如您所看到的,在某些情况下您不能简单地翻译:

(function (x) {
    // ...
}(y));

into:

(function () {
    var x = y;
    // ...
}());

但我认为,如果它可以翻译成第二种形式,那么它应该是为了可读性。特别是对于较大的函数,您必须滚动到函数末尾才能知道函数顶部使用的变量的含义,这很不方便。

回到问题

这意味着我将从问题中翻译这段代码:

(function(global) {
  var turing = {
    VERSION: '0.0.1',
    lesson: 'Part 1: Library Architecture'
  };

  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
})(typeof window === 'undefined' ? this : window);

进入这个:

(function () {
  var global = typeof window === 'undefined' ? this : window;
  var turing = {
    VERSION: '0.0.1',
    lesson: 'Part 1: Library Architecture'
  };

  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
}());

我希望这个答案能解释为什么这两者是等价的,甚至可以写成:

(function (global, turing) {
  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
})(typeof window === 'undefined' ? this : window,
   {VERSION: '0.0.1', lesson: 'Part 1: Library Architecture'});

它的含义仍然是一样的,但同时可读性却大大降低。

也可以看看我的另一个答案 https://stackoverflow.com/questions/5305634/jquery-question-what-does-it-really-mean/5305786#5305786我在其中解释了类似的概念。

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

帮助理解 javascript 全局消除技术 的相关文章

随机推荐

  • 无法使用类型属性选择器在 IE7 中设置新的 HTML5 输入类型的样式

    看来即使使用 shivs 你也不能做类似的事情input type search 在 IE7 中设置新的 HTML5 输入元素的样式 您可以在以下位置查看示例http jsfiddle net 2tmAp http jsfiddle net
  • 使用“AJAX”下载 CSV 文件

    我正在尝试为我的网站完成一项相当简单的任务 但我不确定具体如何去做 我希望用户查看一个表格 然后单击一个按钮 此时用户可以保存该表格该表的内容作为 csv 文件 此请求有时可能非常复杂 因此我生成一个进度页面来提醒用户 除了实际生成 csv
  • 使用 BeautifulSoup 选择所有 div 兄弟姐妹

    我有一个 html 文件 其结构如下 div div div div div div div div div div div div div div 我想选择所有兄弟 div 而不选择第三个和第四个块中的嵌套 div 如果我使用find a
  • 竞争条件:整数的最小和最大范围

    我最近在一次采访中被问到这个问题 给定以下代码 静态整数的最小和最大可能值是多少num import java util ArrayList import java util List public class ThreadTest pri
  • 统一选择将物品分布放入垃圾箱中

    想象一下你有n物品和m垃圾箱 所有物品都是相同的 但箱子是不同的 随机选择一批物品放入垃圾箱的最快算法是什么 例如 想象一下104是将 5 件物品放入 3 个箱子中 将 5 件物品放入 3 个箱子中 有 21 种可能的放置方式 005 01
  • 检查最近x秒内是否添加了mySQL记录

    我有一个 mySQL 数据库和一个表 在其中创建项目的新记录 创建的每个项目都有一个 项目名称 和一个事件创建日期 DATETIME 类型 可以有两个使用相同名称创建的项目 但是如果它们是由同一用户快速连续创建的 则可以安全地假设这是用户的
  • 如何将 Cucumber 测试结果保存到文件

    我有一些可以从控制台运行的黄瓜测试 rake cucumber 是否有命令行选项可以将测试结果存储到文本文件中 Either Run cucumber直接并使用 o From cucumber help o out FILE DIR Wri
  • 使用Python解析XML文件以获取所需数据并将其存储在mongodb数据库中

    我有一个 XML 文件 如下所示 我想从此文件中获取所有事件的以下信息 在类别事件下 开始日期 end date title 根据类别场地 address 地址2 city latitude 经度 name 邮政编码 然后将这些信息存储在
  • HeadersTooLargeException - 响应标头

    我在 Spring mvc 的项目中实现了文件下载 在下载文件时 它在 tomcat 7 服务器上出现以下错误 org apache coyote http11 HeadersTooLargeException An attempt was
  • Google Push-To-Deploy Pipelines - 单元测试因模块导入错误而失败

    当我尝试在 Compute Engine 中的 Google 配置的 Jenkins 服务器上执行构建时 出现以下错误 deployment 5371449468518400 1411607125060 bin sh xe tmp huds
  • 用于测试的 MQTT 代理

    尝试创建一个订阅 MQTT 代理并处理数据的 Python 脚本 然而 MQTT 代理到目前为止还没有收到任何数据 这使得测试变得困难 我发现以下脚本可以订阅主题并打印出有效负载 但我似乎无法连接到测试代理 import paho mqtt
  • ScrollViewer/StackPanel 构造内的 DataBound ListBox 和 Button,其中 Button 出现在 ListBox 内容末尾的下方

    我有以下构造 它显示了 StackPanel 内的 DataBound ListBox 和 Button 后者再次放置在 ScrollViewer 内
  • 从 mysqldump 创建的 SQL 恢复后出现错误 1465“无法在系统表上创建触发器”

    我在 amazon RDS 上运行 mysql 5 6 服务器 并设置一个只读副本 用于使用 mysqldump 创建备份 我尝试使用 all databases 选项 但是当我尝试导入 mysqldump 创建的 SQL 时 我最终从 m
  • 更新 Symfony2 上的composer.phar

    我有一个已经启动的 Symfony2 项目 我需要安装一个新捆绑 https packagist org packages doctrine mongodb odm bundle 正如我所见 我需要向我的composer json 添加一个
  • MySQLdb:操作数应包含 1 列

    我正在尝试使用 Python 和 MySQLdb 将一些数据插入 MySQL 数据库 当我在程序中执行以下函数时 MySQL 返回错误 1241 操作数应包含 1 列 用户 密码和数据库正确 表存在并且所有权限均已授予 def write
  • Pygame:无限滚动相机?

    所以我在 pygame 中编写了一个小型平台游戏 您可以在其中放置块并在它们上跳跃 但是 游戏仅限于窗口的边框 显然 那么如何添加使用 A 和 D 键滚动 相机 的方法呢 这是游戏的代码 import pygame random from
  • 在 Linq To Entities 中使用多个列连接表

    Linq to Entities 中的每个连接示例仅涉及on条款 如果我需要 2 列或更多列来制作 语法是什么join工作 如果可能的话 我还需要一个 Linq to Entities 查询表达式和基于方法的示例 下面是我需要的示例 表 1
  • PHP搜索引擎脚本

  • 哪些工具执行 IL 的编译后修改?

    最近提到 PostSharp 让我想起了这一点 去年我工作的时候 我们正在考虑使用 PostSharp 将检测注入到我们的代码中 这是在 Team Foundation Server 团队构建 持续集成环境中 考虑到这一点 我对 PostS
  • 帮助理解 javascript 全局消除技术

    来自 DailyJS 让我们构建一个 JavaScript 框架 http dailyjs com 2010 02 25 djscript part 1 structure 我不太确定以下代码 显然用作全局抑制技术 到目前为止 我的理解对