我的问题在于objInfo()。如何通过传入变量返回对象?我正在尝试命名我的代码并使用私有/公共变量。
奖金问:你如何改进代码?
// 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);
注意:来自各个地方的来源
答案 0 :(得分:4)
除了命名空间之外,我不清楚你要做什么,但我在下面的分隔符下包含了各种代码审查。首先是更高级别的评论。
这里有几个问题。首先,你几乎从不想要写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
new function() { }
功能,但不那么令人困惑。)
但只是替换Lion
上的原型有点过分了。当你开始进入子类化时,还有其他一些你想要做的事情。 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);
答案 1 :(得分:1)
您基本上已经使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
alert(bab.objInfo(window).innerWidth);
强>
您基本上“短路”了整个bab
对象。只有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"));
我在上面使用了功能继承。我觉得使用它更简单,它充分利用了Javascript的面向对象角色的无类别特性。
作为测试输出,我直接从lion
返回...您通常不会这样做,只是为了表明更改Simba
不会更改lion
。你可以说lion
的饮食优先于cat
的饮食,就像你想要的那样。
诀窍是将你的protected
和public
变量和方法打包在返回的对象中,不要忘记你也可以在你的猫科动物中创建方法。
答案 2 :(得分:0)
您可以使用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。