【问题标题】:JavaScript Object Inheritance with IIFE?IIFE 的 JavaScript 对象继承?
【发布时间】:2017-01-03 14:14:25
【问题描述】:

我不会撒谎,我对 JavaScript 非常了解,也没有完全理解 IIFE 的概念,但是自从我阅读了jQuery Best Practices 然后第一次遇到了这个概念以及后来进行的一些研究,我想到了这个:

( function( MyObject, window, document, $, undefined ) {

    var privateVariable = {};

    MyObject.publicVariable;

    function privateMethod() {}

    myObject.publicMethod() {}

}( window.MyObject = window.MyObject || {}, window, document, window.jQuery ) );

虽然它按预期工作得很好,但我最近觉得需要某种形式的抽象,这样我就可以创建一个具有共享属性和方法的基类以及具有自己逻辑的子对象。

这样我就不需要,比方说,重复每个单独对象中所有子对象共有的 getter

我当然搜索过这个问题,但是我没有找到关于如何用这个概念实现这样的功能的具体信息。

【问题讨论】:

    标签: javascript jquery oop iife


    【解决方案1】:

    使用构造方法怎么样:

    ( function( MyObject, window, document, $, baseClass) {
    
        // calling base class for common properties, methods
        baseClass && baseClass.call(MyObject);
    
        var privateVariable = {};
    
        MyObject.publicVariable;
    
        function privateMethod() {}
    
        myObject.publicMethod() {}
    
    }( window.MyObject = window.MyObject || {}, window, document, window.jQuery, baseClass ) );
    

    【讨论】:

    • 那么,这样做,我会在父类中使用所谓的 getter ,例如,在子类中使用 setter 吗?另外,我是否能够通过预先添加对象名称来访问父上下文中的变量而不使它们公开?以我对 JavaScript 的了解,对我来说看起来不错,但这是一种有效的做法吗?
    • 对我来说,没有这样的最佳或有效做法,如果它对我们有用,那么只需使用它:)。说到底,Javascript 不是 OOP 语言,试图像编写 C# 一样编写 JS,Java 最终会失去语言的力量。
    • 我最接近的工作就是这个,但它看起来更像是一个浮夸的依赖注入,而不是继承,毕竟,因为我在这里注入了我可以使用的称为基础对象@ 987654323@直接代替Child.prototype.getFoo ()
    • Here's 我有一种不同的方法,看起来更像继承,但据我了解 IIFE 概念会自我注入,在这里我必须创建一个全局变量,否则我不能使用new。有可能合并两个世界吗?
    【解决方案2】:

    IIFE 为您提供的唯一东西是一个封闭的范围。你不需要 多个 IIFE,除非您没有说明某些原因。所以,首先, 让我们介绍一下您阅读的“最佳实践”链接的真正含义。

    在浏览器环境中,所有 JavaScript 都在一个范围内执行。 因此,以下两个脚本将具有相同的范围,尽管 不同的文件:

    script_a.js

    var foo = 'bar'
    console.log('foo = ', foo)
    

    script_b.js

    if (foo === 'bar') {
      console.log('foo is still bar')
    }
    

    但是如果我们将每个脚本包装在一个 IIFE 中,则范围会发生变化,script_b 将 不再起作用:

    script_a.js

    (function ()  {
      var foo = 'bar'
      console.log('foo = ', foo)
    }())
    

    script_b.js

    (function () {
      if (foo === 'bar') { // throws an error because `foo` is not defined
        console.log('foo is still bar')
      }
    }())
    

    鉴于 Web 开发的性质,以及带有插件的 jQuery,许多脚本可以 加载并且全局范围被污染。这可能导致难以识别 副作用。因此,建议您将代码包含在其 自己的范围。这是通过 IIFE 完成的,因为函数有自己的 本地作用域,函数在加载时调用。

    根据您的example,您似乎只想要可组合的 对象,以便您可以在期间将它们分隔在单独的文件中 发展。这是module pattern的明确用法:

    script_c.js

    var MY_NAMESPACE = (function () {
      var privateFoo = 'foo'
    
      return {
        getFoo: function getFoo () {
          return privateFoo
        }
      }
    }())
    

    script_d.js

    (function (NAMESPACE) {
      var privateBar = 'bar'
    
      NAMESPACE.getBar = function getBar () { return privateBar }
    }(MY_NAMESPACE))
    

    script_e.js

    console.log(MY_NAMESPACE.getFoo()) // 'foo'
    console.log(MY_NAMESPACE.getBar()) // 'bar'
    

    注意MY_NAMESPACE 是一个全局变量。这是你必须要做的 是唯一的,因为它很容易被一些后来加载的内容覆盖 可能会覆盖您的全局变量的脚本。

    我没用过,但是有一个叫stampit的库 扩展了这种模式并使其易于使用。

    综上所述,您可以将 MY_NAMESPACE 对象扩展为 一个新对象:

    script_f.js

    var CHILD_NAMESPACE = Object.create(MY_NAMESPACE)
    
    CHILD_NAMESPACE.fooOrBar = (function (NS) {
      var counter = 0
      return function () {
        var answer = (counter % 2 === 0) ? NS.getFoo() : NS.getBar()
        counter += 1
        return answer
      }
    }(CHILD_NAMESPACE))
    

    当然,以上所有脚本都可以包含在一个整体中 IFFE 将您的代码完全包含在自己的范围内。

    【讨论】:

      猜你喜欢
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      • 2012-01-31
      • 2013-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多