【问题标题】:JavaScript Module Pattern - What about using "return this"?JavaScript 模块模式 - 使用“return this”怎么样?
【发布时间】:2010-04-26 12:35:14
【问题描述】:

在阅读了有关模块模式的一些内容后,我看到了一些返回您想要公开的属性的方法。

除了私有属性和方法之外,最常见的方法之一是在“return”语句中声明您的公共属性和方法。类似的方式(“Revealing”模式)是提供对您想要公开的属性和方法的简单引用。最后,我看到的第三种技术是在模块函数中创建一个新对象,在返回该对象之前为其分配新属性。这是一个有趣的想法,但需要创建一个新对象。

所以我在想,为什么不直接使用this.propertyName 来分配您的公共属性和方法,最后使用return this?这种方式对我来说似乎更简单,因为您可以使用通常的 varfunction 语法创建私有属性和方法,或者使用 this.propertyName 语法来声明您的公共方法。

这是我建议的方法:

(function() {

var privateMethod = function () {
    alert('This is a private method.');
}

this.publicMethod = function () {
    alert('This is a public method.');
}

return this;

})();

使用上述方法有什么优点/缺点吗?其他人呢?

【问题讨论】:

  • 您考虑过“这”到底是什么吗?你在哪里添加你的 publicMethod?

标签: javascript design-patterns module-pattern


【解决方案1】:

您的函数没有对象上下文,因此在这种情况下this 引用了全局window 对象。您分配给 this 的每个属性都会自动污染全局命名空间。

(function() {
    console.log(this == window); // true

    this.publicMethod = function () {
        alert('This is a public method.');
    }

})();

console.log(publicMethod); // function()

你可以显式地传递一个对象来告诉它使用哪个上下文。

var MYAPP = {};

(function() {
    // 'this' will now refer to 'MYAPP'
    this.publicMethod = function () {
        alert('This is a public method.');
    }
}).call(MYAPP);

console.log(publicMethod); // undefined
console.log(MYAPP.publichMethod); // function()

你可以用其他风格来写:

var MYAPP = (function(my) {
    var my;
    ⋮
    return my;
})(MYAPP);

我们到达an already discussed pattern。有关详细信息,请参阅达斯汀在Scoping anonymous functions 上的文章。

【讨论】:

  • 非常感谢。我不知道匿名函数中“this”的行为。
  • 与匿名函数无关。这与函数(任何函数,可以使用函数声明或函数表达式创建)的调用方式有关。如果您使用表达式 f() 调用存储在变量 f 中的函数(例如,由函数声明 function f() {} 或通过分配给变量的函数表达式定义:var f = function() {};),this 将始终成为全局对象。
【解决方案2】:

我会推荐您将公共属性和方法添加到然后返回的匿名对象的样式:

var myModule = (function() {
    function privateMethod() { ... }
    function publicMethod() { ... }

    return { publicMethod: publicMethod };
})();

【讨论】:

  • 嗯,是的,除非您返回的东西会立即被扔掉。
  • 我很好奇杰森的意思。使用匿名对象作为返回会出现什么问题?这似乎是我在使用模块模式时遇到的最好的技术。
  • 我认为 Jason 指的是被省略或推断的代码,因为我们正在讨论模块模式。我将更新我的示例。
【解决方案3】:

如果您想发布方法,请执行以下操作:

var export = (function() {

var privateMethod = function () {
  alert('This is a private method.');
}
var export = {};

export.publicMethod = function () {
  alert('This is a public method.');
}

return export;

})();

【讨论】:

    【解决方案4】:

    另一种选择是完全避免 this 引用。定义一个创建并返回匿名对象的函数。

    function makeThing(someAttribute) {
      var privateVariable = 42;
    
      function someMethod() {
        return privateVariable;
      }
    
      return {
        "publicMethodName": someMethod,
        "getAttribute": function() {
          return someAttribute;
        }
      };
    }
    
    var thing = makeThing(99);
    thing.publicMethodName();
    thing.getAttribute();
    

    【讨论】:

      【解决方案5】:

      揭示模块模式:

      var m1 = (function(){ return {method: mthod} })();
      var m2 = new function Singleton(){ return {method: mthod} };
      var m3 = ({}).prototype = {method: method};
      var m4 = ({}).prototype = (function(){ ... })();
      var m5 = (function(){}).prototype = {} || (function(){ ... })();
      
      var m6 = (function(extendee){
          return extendee.prototype = {attr3: 'attr3'};
      })({currentAttr1: 1, currentAttr2: 2});
      

      另外,如果您需要方法链接:

      var m = (function(){}).prototype = (function(){
          var thus = m;  // this
          console.log('m this-------', thus);
      
          function fn(){
              console.log('fn', thus);
              return thus;
          }
          function f(){
              console.log('f', thus);
              return 'poop';
          }
      
          return {f: f, fn: fn};
      })();
      
      console.log('M:', m, 'm.fn', m.fn(), 'm.fn.f', m.fn().f());
      

      还有更多方法,您也可以对模块进行主角化。

      【讨论】:

        猜你喜欢
        • 2021-12-30
        • 1970-01-01
        • 2021-11-09
        • 1970-01-01
        • 2018-03-24
        • 2014-06-29
        • 2015-10-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多