代码之家  ›  专栏  ›  技术社区  ›  Matrym

命名空间,哦,JS,我做得对吗?

  •  1
  • Matrym  · 技术社区  · 15 年前

    额外的问题:你会如何改进代码?

    // Namespace all my code
    var bab = new function() {
    
        // Declare cat object
        function cat()
        {
          this.eyes = 2;
          this.legs = 4;
          this.diet = 'carnivore';
    
          return true;
        }
    
        // Declare lion object
        function lion()
        {
          this.mane = true;
          this.origin = 'Africa';
          this.diet = 'people'; // has priority over cat's diet
    
          return true;
        }
    
        // Make lion a subclass of cat
        lion.prototype = new cat();
    
        // Create an instance of class lion
        var simba = new lion();
    
        // Share diet publicly
        this.objInfo = function(name) {
            return name; // simba works, name doesn't
        };
    
    };
    
    alert(bab.objInfo('simba').diet);
    

    3 回复  |  直到 15 年前
        1
  •  4
  •   T.J. Crowder    15 年前

    除了名称空间之外,我还不清楚您要做什么,但是我在下面的分隔符下加入了一个代码评审。更多高层评论在先。

    这里有几个问题。首先,你几乎 想写作吗 new function() { } . 这是一种非常先进的技术,很容易出错(而且任何维护代码的人都很容易误解)。下面有一个例子,说明了另一种不那么令人费解的方法来获得相同的效果(加上其他一些好处)。

    Cat Lion

    var Animals = (function() {
        var publics = {};
    
        // A Cat
        publics.Cat = Cat;
        function Cat() {
            this.eyes = 2;
            this.legs = 4;
            this.diet = 'carnivore';
        }
    
        // A Lion
        publics.Lion = Lion;
        function Lion() {
            this.mane = true;
            this.origin = 'Africa';
            this.diet = 'people'; // has priority over cat's diet
        }
        Lion.prototype = new Cat();
    
        // Return our public symbols
        return publics;
    })();
    
    // Usage
    var l = new Animals.Lion();
    alert(l.eyes); // alerts "2" (inherited from Cat)
    alert(l.diet); // alerts "people" (overridden by Lion)
    

    (当然,你可以打电话 publics 你还想要什么- pubs , p this 在你身体的最外层 功能,但不那么混乱。)

    但只是换个原型而已 狮子 Here's a blog post

    在通过字符串查找内容方面,您可以在任何对象上使用括号表示法:

    var obj = {};
    obj.foo = 42;
    alert(obj["foo"]); // alerts "42" by retrieving the property "foo" from `obj`
    var x = "f" + "o" + "o";
    alert(obj[x]);     // alerts "42" by retrieving the property "foo" from `obj`
    


    下面是代码回顾:

    // Namespace all my code
    // [TJC] Use the (function() { ... })(); mechanism described above rather than
    // `new function() { ... }`, which is fairly confusing to the reader and troublesome
    // to use inside inner functions (see below)
    var bab = new function() {
    
        // Declare cat object
        // [TJC] Convention is to use initial caps for constructor functions,
        // e.g. "Cat" not "cat"
        function cat()
        {
          this.eyes = 2;
          this.legs = 4;
          this.diet = 'carnivore';
    
          // [TJC] Don't return anything out of constructor functions
          return true;
        }
    
        // Declare lion object
        // [TJC] "Lion" rather than "lion" would be more conventional
        function lion()
        {
          this.mane = true;
          this.origin = 'Africa';
          this.diet = 'people'; // has priority over cat's diet
    
          // [TJC] Don't return anything out of constructor functions
          return true;
        }
    
        // Make lion a subclass of cat
        // [TJC] There are several other things you want to consider in
        // addition to replacing the prototype
        lion.prototype = new cat();
    
        // Create an instance of class lion
        // [TJC] From your usage below, it looks like you
        // want to be able to look up "simba" using a string
        // later. So use the below rather than this commented-out
        // line:
        //var simba = new lion();
        var instances = {};           // [TJC]
        instances.simba = new lion(); // [TJC]
    
        // Share diet publicly
        // [TJC] You don't need a function for this at all, just
        // expose "instances" directly. But if you want it:
        this.objInfo = function(name) {
                // [TJC] To look up something by name using a string,
                // use brackets:
            //return name; // simba works, name doesn't
                return instances[name]; // [TJC]
        };
    
    };
    
    alert(bab.objInfo('simba').diet);
    
        2
  •  1
  •   Peter Ajtai    15 年前

    objInfo() 在里面 bab objInfo() 简单地返回传递给它的内容。

    在你的特殊情况下, objInfo("simba") 从那以后就没用了 objInfo() 只返回字符串 "simba" :

        ...
        // Share diet publicly
        this.objInfo = function(name) { // <-- If name == "simba"
            return name; // <-- This will return "simba" not the Object simba!!!
        };
    
    };
    
    alert(bab.objInfo('simba').diet);​ // This will check for the diet property of
                                      //   the string "simba". So it won't work.
    

    objInfo()

    请尝试以下示例:

    alert(bab.objInfo('simba'));            // This will alert "simba"
    alert(bab.objInfo('noodles'));          // This will alert "noodles"
    alert(bab.objInfo(window).innerWidth);  // This will give you the innerWidth of
    

    jsFiddle example of alert(bab.objInfo(window).innerWidth);


    你基本上“短路”了你的整个 巴布 对象。只有 objInfo


    我会这样做:

    // Namespace all my code
    var bab = new function() {    
        var cat = function() // Declare cat object
        {
          var protected = {}; // Protected vars & methods
          protected.eyes = 2;
          protected.legs = 4;
          protected.diet = 'carnivore';
          return protected; // Pass protected to descendants
        }
        var lion = function()
        {     
          var protected = cat();  // Make lion a subclass of cat        
          var public = {}; // Public vars & methods
          public.legs = protected.legs; // Make 1 protected var public
          public.mane = true;
          public.origin = 'Africa';
          public.diet = 'people'; // has priority over cat's diet
          return public; // Make public vars available
        }    
        var simba = lion();     // Create an instance of class lion
        simba.diet = "Asparagus"; // Change simba, but not lion
        // Get property of choice
        this.objInfo = function(property) {
            return ("Simba: " + simba[property] +
                    " - Lion (this is usually private. Shown for testing.): " +
                    lion()[property]);
        };
    };
    alert(bab.objInfo("diet"));
    

    jsFiddle example


    我在上面使用了函数继承。我发现它使用起来更简单,并且很好地利用了Javascript面向对象角色的无类特性。

    lion Simba 狮子 狮子 的饮食优先于 cat 的饮食,就像你想要的。

    诀窍是包装你的 protected public 返回对象中的变量和方法,并且不要忘记您还可以在您的猫科动物中创建方法。

        3
  •  0
  •   palswim    15 年前

    你可以用 eval ,但我不想推荐。

    您可以通过在数组中“注册”狮子来改进脚本。

    // Namespace all my code
    var bab = (function() {
            // Declare cat object
            function cat() {
                this.eyes = 2;
                this.legs = 4;
                this.diet = 'carnivore';
    
                return true;
            }
    
            // Declare lion object
            function lion() {
                this.mane = true;
                this.origin = 'Africa';
                this.diet = 'people'; // has priority over cat's diet
    
                return true;
            }
    
            // Make lion a subclass of cat
            lion.prototype = new cat();
    
            // Create an instance of class lion
    //      var simba = new lion();
            var lions = {}; // Create a "lions" object to collect all of the lion instances
            lions["simba"] = new lion();
    
        return {
            // Share diet publicly
            objInfo: function(name) {
                return lions[name];
            };
        }
    })();
    
    alert(bab.objInfo('simba').diet);
    

    Public and Private in JavaScript .