【问题标题】:How to append to a JavaScript namespace created from a closure?如何附加到从闭包创建的 JavaScript 命名空间?
【发布时间】:2013-02-01 18:19:41
【问题描述】:

我有一个以下格式的命名空间,允许公共和私有成员:

function A() {
    return('a');
}

namespace1 = (function () {
    // private
    namespace2 = (function() {
        // private
        prC = function () {
            return(namespace1.puB() + 'c');
        };
        puC = function () {
            return(prC());
        };
        // public
        return({
            puC: puC
        });
    })();
    prB = function () {
        return(A() + 'b');
    };
    puB = function () {
        return(prB());
    };
    // public
    return({
        puB: puB,
        namespace2: namespace2
    });
})();

document.write('A() = '); try {  document.write(A()); } catch (ex) { document.write('inaccessible'); }
document.write('<BR />');
document.write('namespace1.prB() = '); try {  document.write(namespace1.prB()); } catch (ex) { document.write('inaccessible'); }
document.write('<BR />');
document.write('namespace1.puB() = '); try {  document.write(namespace1.puB()); } catch (ex) { document.write('inaccessible'); }
document.write('<BR />');
document.write('namespace1.namespace2.prC() = '); try {  document.write(namespace1.namespace2.prC()); } catch (ex) { document.write('inaccessible'); }
document.write('<BR />');
document.write('namespace1.namespace2.puC() = '); try {  document.write(namespace1.namespace2.puC()); } catch (ex) { document.write('inaccessible'); }

输出:

A() = a
namespace1.prB() = inaccessible
namespace1.puB() = ab
namespace1.namespace2.prC() = inaccessible
namespace1.namespace2.puC() = abc

如何将公共和私有成员都附加到这样的命名空间(即:来自不同文件)?

Here's a JSFiddle.

【问题讨论】:

  • 这只是一堆返回对象的自调用函数,问题是返回的对象不包含您尝试访问的属性,没有清除某些私有或公共的东西JS。要向对象添加更多方法,您只需使用点或括号表示法即可,并且可以对函数进行原型化。由于您没有使用 var 关键字清除这些变量,因此它们是全局的,并且可以在窗口范围内访问,请参见 FIDDLE ???
  • 在您的上下文中,prB() 根本不是私有的。它是全球性的。尝试运行prB()

标签: javascript namespaces javascript-namespaces


【解决方案1】:

“我怎样才能将公共和私有成员都附加到这样的命名空间......”

好吧,你的函数被暴露了,因为你没有用var正确声明你的变量。

但是一旦你解决了这个问题,你可以从任何可以引用你的 namespace 对象的代码中添加更多公开的属性(因为所有属性都是公开的)


添加更多引用本地(私有)函数的属性,您需要一个新函数和变量范围。

只需调用引用namespace 对象的函数,在该函数内创建一些函数,然后添加引用这些本地函数的属性。

// Other file

(function() {
    var newLocalFunc = function() {
        // local function
    }

    var anotherLocalFunc = function() {
        // local function
    }

    namespace1.exposedFunc = function() {
        return newLocalFunc()
    }
    namespace1.namespace2.anotherExposedFunc = function() {
        return anotherLocalFunc()
    }
})();

再一次...不要忘记将var 放在原始代码中的变量之前。

【讨论】:

    【解决方案2】:

    没有var关键字声明的任何变量都将在全局范围中。所以你的puB() 函数不是不可访问或私有的,它只是不是namespace1 函数返回的对象的成员。以window.prB() 为例,您会看到该方法存在于window 对象的全局范围内。

    <head>
        <script type="text/javascript">
            obj1 = {}; //in global scope
            var obj2 = {}; //in global scope. Although used the var keyword, this line itself is in the global scope; so the variable.
            function someFunc() {
                obj3 = {}; //in global scope
                var obj4 = {}; //'so-called' private (inaccessible from global scope)
            }
        </script>
    </head>
    

    用于在同一个“命名空间”(或者说是对象)下组合两个不同的 JS 文件:

    文件-1.js

    var namespace1 = (function() {
        // some code...
        var namespace2 = (function() {
            // some code...
            return {
                obj2: 'value2'
            };
        })();
    
        return {
            obj1: 'value1'
        };
    })();
    

    文件-2.js

    namespace1.namespace3 = (function() {
        // some code...
        var ns4 = (function() {
            // some code...
            return {
                obj4: 'value4'
            };
        })();
    
        return {
            obj3: 'value3',
            namespace4: ns4
        };
    })();
    

    什么是什么:

    • namespace1 在全局范围内声明;所以它是可访问的 来自任何地方,它是我们的主要对象。
    • namespace2 无法访问(私有)。
    • namespace3 在全局范围内不可访问,但可作为 namespace1的成员;例如:namespace1.namespace3
    • namespace4 可作为 namespace1 的成员访问。例如。: namespace1.namespace4

    所以;我们的主要对象 namespace1 的成员是:

    namespace1 = {
        obj1: String,
        namespace3: {
            obj3: String,
            namespace4: {
                obj4: String
            }
        }
    };
    

    【讨论】:

      【解决方案3】:

      这里离堪萨斯很远。

      您不能将事物“声明”为公开或私有。
      只要您在函数内部定义事物,然后选择返回特定事物,或将它们附加到您作为参数传入的对象/数组中,那么您将拥有对这些事物的“公共”(外部)访问权限,之后函数返回。

      为了获得“私人”访问权限,您返回一个引用内部某些内容的函数。

      var Wallet = function (amount, overdraft_limit) {
          var balance = 0,
              overdraft = overdraft_limit || 0,
      
              deposit_funds = function (funds) { balance += funds; return true; },
      
              withdraw_funds  = function (request) {
                  var funds = 0;
                  balance -= request;
                  funds = request;
                  return funds;
              },
      
              validate_request = function (pin) { /* ... */ },
      
              sufficient_funds = function (val) { return val <= (balance + overdraft); },
      
              add = function (pin, deposit) {
                  if (!validate_request(pin) || deposit <= 0) { return false; }
      
                  var result = deposit_funds(deposit);
                  return result;
              },
      
              deduct = function (pin, withdrawl) {
                  if (!validate_request(pin) || withdrawl <= 0) { return false; }
                  if (!sufficient_funds(withdrawl)) { return false; }
      
                  var funds = withdraw_funds(withdrawl);
                  return funds;
              },
      
              check = function () { return balance; },
      
              public_interface = { deduct : deduct, add : add, check : check };
      
          return public_interface;
      };
      
      
      var myWallet = Wallet(30, 20);
      
      var cash = myWallet.deduct(40);
      cash;             //  40
      myWallet.check(); // -10
      
      myWallet.balance = 40000000000;
      
      cash = myWallet.deduct(4000);
      cash;  // === false
      

      通过在我的“构造函数”内部构建函数,这些函数可以访问balance,我返回该“公共”对象的变量可以调用方法与“私有”数据交互,但不能访问它或通过任何方法修改它,但使用那些“公共”功能。

      使用 IIFE 将这些东西嵌套 8 层深,使用的闭包概念与我刚刚演示的完全相同。

      明确决定要返回什么,不返回什么。
      您发送到世界的功能是public。未返回或附加到对象的函数内部的函数/等是私有的。
      它们已被返回的“构造函数”函数关闭,现在它们 100% 不可访问,除非使用构造函数内部构建的函数,这些函数引用私有变量,并作为公共方法返回。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-06
        • 1970-01-01
        • 2010-12-13
        • 1970-01-01
        • 1970-01-01
        • 2016-04-14
        相关资源
        最近更新 更多