草庐IT

javascript - 帮助理解 javascript 全局消减技术

coder 2024-07-23 原文

来自 DailyJS "Let's build a JavaScript Framework"我不太确定以下代码,显然用作全局减排技术。

到目前为止,我的理解还停留在 (function(){}) 上。我了解设置 turing var,将 global.turing 设置为 turing,并返回 window 或 this(如果不在浏览器中),但是 (function(global){})(this or 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);

作为:
function functionName(x) {
    // ...
}
functionName(y);

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

所以这:
(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);

其中(如果您只调用一次)是通常 (见下文异常(exception))也与此相同:
function functionName() {
    var x = y;
    // ...
}
functionName();

回到匿名立即调用的函数,这个:
(function (x) {
    // ...
})(y);

与此相同:
(function () {
    var x = y;
    // ...
})();

对于大多数人来说,这可能具有更明显的含义。 (这里立即调用的函数没有参数,只是为了给我们一个变量和其他嵌套函数的隔离范围,这样我们就不会污染外部或全局范围——这也是在首先立即调用匿名函数。)

关于括号

顺便说一句,这个:
(function () {
    // ...
})();

与此相同:
(function () {
    // ...
}());

由于语言不明确,函数周围的括号是必需的,但它们可能包括 ()实际调用该函数,或者它们可能不调用该函数 - 尽管有些人认为这里的第二种形式看起来更清晰。见 this explanation by Douglas Crockford了解更多细节以及为什么他认为第一个版本看起来像“狗球”。

异常(exception)

之前我说过这个:
(function (x) {
    // ...
}(y));

与此相同:
(function () {
    var x = y;
    // ...
}());

这在大多数情况下对于一个参数是正确的(它不会在外部范围内屏蔽同名变量,同时取决于它的值)并且通常对于多个参数是正确的(如果他们不这样做) t 也相互依赖)。我希望它会在示例中变得更加清晰。

当我们有这段代码时:
(function (x) {
    // ...
}(x + 1));

那么我们不能把它翻译成:
(function () {
    var x = x + 1;
    // ...
}());

因为在第一个版本中,我们将 1 添加到 x并将结果绑定(bind)到 x一旦我们进入函数内部,我们就只有内部的 x使用(甚至新的 let 语句也无济于事)。

另一个例子:
(function (x, outer_x) {
    // ...
}(1, x));

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

概括

如您所见,在某些情况下您不能简单地翻译:
(function (x) {
    // ...
}(y));

进入:
(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'});

它仍然意味着相同,同时可读性要低得多。

另见 my other answer我在这里解释了类似的概念。

关于javascript - 帮助理解 javascript 全局消减技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5318921/

有关javascript - 帮助理解 javascript 全局消减技术的更多相关文章

  1. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  2. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  5. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  6. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  7. ruby - 易于初学者理解的 Ruby 库 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5

  8. ruby - 在 RSpec 中 stub /模拟全局常量 - 2

    我有一个gem,它有一个根据Rails.env的不同行为的方法:defself.envifdefined?(Rails)Rails.envelsif...现在我想编写一个规范来测试这个代码路径。目前我是这样做的:Kernel.const_set(:Rails,nil)Rails.should_receive(:env).and_return('production')...没关系,只是感觉很丑。另一种方法是在spec_helper中声明:moduleRails;end而且效果也很好。但也许有更好的方法?理想情况下,这应该有效:rails=double('Rails')rails.sho

  9. ruby-on-rails - 需要帮助最大化多个相似对象中的 3 个因素并适当排序 - 2

    我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night

  10. ruby - 将全局 $stdout 重新分配给控制台 - ruby - 2

    我正在尝试将$stdout设置为临时写入一个文件,然后返回到一个文件。test.rb:old_stdout=$stdout$stdout.reopen("mytestfile.out",'w+')puts"thisgoesinmytestfile"$stdout=old_stdoutputs"thisshouldbeontheconsole"$stdout.reopen("mytestfile1.out",'w+')puts"thisgoesinmytestfile1:"$stdout=old_stdoutputs"thisshouldbebackontheconsole"这是输出。r

随机推荐