为什么在创建范围时将参数传递给匿名函数

Why passing parameters to anon function when creating scoping

提问人:Merc 提问时间:5/3/2016 更新时间:5/3/2016 访问量:40

问:

对不起,这个标题很烂,但我想不出更好的标题。

Polymer 中的 ShadowDOM.js 文件执行此操作:

(function(scope) {
  "use strict";
  var unsafeUnwrap = scope.unsafeUnwrap;
  var wrap = scope.wrap;
  var nonEnumDescriptor = {
    enumerable: false
  };
  function nonEnum(obj, prop) {
    Object.defineProperty(obj, prop, nonEnumDescriptor);
  }
  function NodeList() {
    this.length = 0;
    nonEnum(this, "length");
  }
  NodeList.prototype = {
    item: function(index) {
      return this[index];
    }
  };
  nonEnum(NodeList.prototype, "item");
  function wrapNodeList(list) {
    if (list == null) return list;
    var wrapperList = new NodeList();
    for (var i = 0, length = list.length; i < length; i++) {
      wrapperList[i] = wrap(list[i]);
    }
    wrapperList.length = length;
    return wrapperList;
  }
  function addWrapNodeListMethod(wrapperConstructor, name) {
    wrapperConstructor.prototype[name] = function() {
      return wrapNodeList(unsafeUnwrap(this)[name].apply(unsafeUnwrap(this), arguments));
    };
  }
  scope.wrappers.NodeList = NodeList;
  scope.addWrapNodeListMethod = addWrapNodeListMethod;
  scope.wrapNodeList = wrapNodeList;
})(window.ShadowDOMPolyfill);

简单的问题:为什么要传递参数?window.ShadowDOMPolyfill

是的,这是一个立即执行的匿名函数。是的,所有变量都将保持在函数内,避免污染。yes 将与 相同。scopewindow.ShadowDOMPolyfill

这是我见过很多次的模式。我完全理解为什么不要用变量等污染全球范围是件好事。但是,为什么要通过窗口。ShadowDOMPolyfill 作为第一个参数?据我所知,Window 对象在函数中完全可用......那么上面的代码和:

(function() {
  "use strict";
  var scope = window.ShadowDOMPolyfill;
  ...
})();

...?

JavaScript 作用域

评论

1赞 Jamiec 5/3/2016
我的猜测:个人喜好。
1赞 Madara's Ghost 5/3/2016
外观更简洁的 API。也许有一点点性能提升。但从功能上讲,它们都做同样的事情。
0赞 Merc 5/3/2016
哇。。。我没想到会这样。我认真地认为我错过了 Javascript 的一些重要部分,即使我已经写了很多代码(这不是第一次了!
0赞 adeneo 5/3/2016
看起来更干净,将变量括起来,因此它不容易在 IIFE 之外被覆盖,对于这样做的库来说更容易最小化等等,尤其是不会最小化,但会最小化。window.propertyscope
0赞 Merc 5/3/2016
“看起来更干净” -- 哼 好吧。 “在IIFE之外不容易被覆盖” -- 为什么在IIFE之外更难覆盖它?“更容易最小化”——为什么?我很想把这看作是一个答案,一旦它稍微扩展了......

答:

4赞 Madara's Ghost 5/3/2016 #1

在参数列表中定义函数所需的参数以完成分配给它的工作被认为是很好的做法。

虽然完全可以按照你提议的方式去做,但它鼓励了一个说谎的 API,从某种意义上说,你无法查看函数签名并理解函数中的内容。

在这个特定的例子中,这两个示例在功能上是相同的,但是,假设有更多的参数,它们的用法和定义分散在函数体中。

(function(oneThing, anotherThing, aThirdThing) {
  ...
})(window.oneThing, window.anotherThing, window.aThirdThing);

(function() {
  ... // with your vars somewhere inside.
})();

在示例中,您必须与开发人员强制执行约定,以始终将这些定义放在顶部,以保持可读性。但是,该语言已经帮助您通过参数列表强制执行。

评论

0赞 T.J. Crowder 5/3/2016
我非常喜欢这种观点。
0赞 T.J. Crowder 5/3/2016
它也更适合回答整个问题(比我的)。
2赞 Pablo Lozano 5/3/2016 #2

另一个可能的原因是它使测试更容易,并且与其他环境更兼容。Angular 也有类似的方法,因为他们建议使用变量 $window 而不是 window,尽管它们具有相同的值。

一个简单的例子:

function myFunction(globalContext) {
   //adding stuff to the global object
}

myFunction(window || myGlobalObject)

此函数可以在 Nodejs、Rhino 或 Nashorn 引擎(不是浏览器环境)中作为参数 、 a 或完全不同的全局对象接收windowmocked window