【问题标题】:Pro Javascript Design Patterns errata?Pro Javascript 设计模式勘误表?
【发布时间】:2011-05-26 02:14:37
【问题描述】:

谁能确认Pro Javascript 设计模式第 3 章中的这些示例存在缺陷,如果有,从根本上如何 - 它们与产生“ JavaScript 中的类常量?谢谢。

var Class = (function() {

  // Constants (created as private static attributes).
  var UPPER_BOUND = 100;

  // Privileged static method.
  this.getUPPER_BOUND() {//sic
    return UPPER_BOUND;
  }

  ...

  // Return the constructor.
  return function(constructorArgument) {
    ...
  }
})();

/* Usage. */

Class.getUPPER_BOUND();

/* Grouping constants together. */

var Class = (function() {

  // Private static attributes.
  var constants = {
    UPPER_BOUND: 100,
    LOWER_BOUND: -100
  }

  // Privileged static method.
  this.getConstant(name) {//sic
    return constants[name];
  }

  ...

  // Return the constructor.
  return function(constructorArgument) {
    ...
  }
})();


/* Usage. */

Class.getConstant('UPPER_BOUND');

【问题讨论】:

  • Javascript 不是经典的。学习原型或使用另一种语言?阅读 JS:好的部分,而不是你正在阅读的内容。
  • @GlennFerrieLive 主要是为了记录,我确实/确实知道原型继承机制,但可以看到你为什么不这样认为

标签: javascript design-patterns errata


【解决方案1】:

我认为,这是错误的。如前所述,“this”指的是窗口对象,代码也有语法错误。以下代码应实现所需目标:

var Class = (function () {

    // Private static attributes.

    var constants = {
        UPPER_BOUND: 100,
        LOWER_BOUND: -100
    };            

    var sc = function (constructorArgument) {

    };

    // Privileged static method.
    sc.getConstant = function (name) {
        return constants[name];
    };

    // Return the constructor.
    return sc;
})();

alert(Class.getConstant('UPPER_BOUND'));

【讨论】:

  • 这就是本书希望通过拥有特权静态方法来展示的内容,但他们的示例却大错特错。谢谢你。
【解决方案2】:

代码可以简单地固定为

var Class = {
  UPPER_BOUND: 100
};

其余代码设计过度或明显错误,应忽略。

如果您关心只读,请将可写标志设置为 false(注意默认为 false)。

var Class = {};
Object.defineProperty(Class, "UPPER_BOUND", {
  value: 100,
  enumerable: true,
  configurable: true
});

【讨论】:

  • 我的问题是 UPPER_BOUND 是可变的,因此不是恒定的
  • 我也会将可配置设置为 false,但是是的,这很有效 - 谢谢。我猜这本书早于 Object.defineProperty
  • @Joffer 始终保持可配置为真。当您尝试修补或扩展类/库/第 3 方的东西时,您意识到您无法覆盖或删除属性的那一天是您诅咒该库如此死板的那一天。
【解决方案3】:

警惕任何声称是“专业”的东西。我没看过书,但我对代码的看法如下:

> var Class = (function() {
> 
>   // Constants (created as private static attributes).

“属性”一词是错误的,应该是“属性”或“变量”,因为它们是变量,也可以描述为局部激活/变量对象的属性。

>   var UPPER_BOUND = 100;
> 
>   // Privileged static method.  
>   this.getUPPER_BOUND() {//sic

代码将在this 是窗口/全局对象的全局上下文中执行。所以如果有一个全局的 *getUPPER_BOUND* 函数,它会在没有参数的情况下被调用。后面是一个大括号 ({),它在一个块不能出现的地方打开一个块,所以这是一个语法错误。

我认为以下是故意的:

    this.getUPPER_BOUND = function() {

它创建全局/窗口对象的 getUPPER_BOUND 属性,当代码运行时,该属性被分配给 RHS 上的匿名函数。

>     return UPPER_BOUND;   }
> 
>   ...
> 
>   // Return the constructor.
>   return function(constructorArgument) {

这是分配给全局变量“Class”的函数。

>     ... 
>   }
>  })();

修复后它可能会“工作”,但并不优雅。任何代码中有如此明显错误的书都没有经过仔细编写,而且在出版之前肯定没有经过适当的审查。

使用信誉良好的在线资源并继续就您不理解或认为有误的任何问题提出问题。还有其他讨论 javascript 的论坛可以为技术问题提供更详细的答案。

【讨论】:

    【解决方案4】:

    看看这个作为一个不错的选择:http://www.klauskomenda.com/code/javascript-programming-patterns/

    对于不可变的公共属性,如建议的那样,使用 Object.freeze 和 John Resig 的好建议:http://ejohn.org/blog/ecmascript-5-objects-and-properties/

    为了不破坏你的全局范围,向 jQuery 添加命名空间:Is it possible to create a namespace in jQuery?

    【讨论】:

    • 是的,总的来说,我已经有 7 年没读过书了。我知道有一些不错的,但我可以在线获得所需的一切。
    • 感谢您的链接。我认为 Revealing Module 模式对枚举和单例很有用。如果我错了,请原谅我,但我不认为如果该类的实例化是不受限制的,那么所呈现的任何模式都可以用于为该类提供公共不可变字段,这是我转录的模式的意图题。您知道成功实现此意图的任何模式吗?我正在考虑将 Object.freeze(obj.prototype) 与链接中自定义对象标题下演示的公式结合使用。
    • 你是对的,那篇文章没有讨论不可变的公共属性。我认为这个概念在编写时并不存在。 Object.freeze 确实做到了,请查看 John Resig 的精彩帖子:ejohn.org/blog/ecmascript-5-objects-and-properties。请注意,这需要更高级的 javascript 支持。
    • 这是一种单独的考虑。我通过向 jQuery 添加一个简单的命名空间插件 (stackoverflow.com/questions/527089/…) 对其进行了调整,因此我可以执行以下操作:jQuery.myNamespace.safeFromGlobalScopeStuffHere。我仍然认为我发布的 klauskomenda 文章中概述的原则非常合理。
    • @Milimetric 你读过 RobG 的回答吗?该代码甚至在语法方面都无效。命名空间也是模块加载而不是模块编写的工具
    【解决方案5】:

    让它工作,但不确定这是否是作者的意图。

    var Class = (function()
    {
        // Constants (created as private static attributes).
        var constants =
        {
            UPPER_BOUND: 100,
            LOWER_BOUND: -100
        };
    
        // Return the method(s).
        return {
            getConstant: function(name)
            {
                return constants[name];
            }
        }
    }());
    
    console.log(Class.getConstant('UPPER_BOUND')); // shows "100" in console
    

    【讨论】:

    • 您的解决方案避免了 getConstant 成为窗口属性的问题,但我们仍然必须实例化该类。
    • 这个怎么样?而是直接返回方法。这样,我们不必先启动类。
    • 现在的问题是我们不能实例化这个类
    【解决方案6】:

    这样怎么样?

    /* Grouping constants together. */
    var Class = (function() {
      // Private static attributes.
      var constants = {
         UPPER_BOUND: 100,
         LOWER_BOUND: -100
      }
    
      // Return the constructor.
      return new function(constructorArgument) {
         // Privileged static method.
         this.getConstant = function(name) {//sic
           return constants[name];
         }
       }
    })();
    
    console.log(Class.getConstant("LOWER_BOUND"));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-10
      • 2010-09-20
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多