我想拥有一个具有多级方法和属性的对象。顶级将具有属性和方法。其中一些属性将作为二级方法和属性的名称空间。
e.g。
//first level methods
base.doStuff();
base.doMore();
//second level methods
base.level2.doStuff();
直接做第一级:
function Base(foo) {
this.foo = foo;
}
Base.prototype.doStuff = function () {
console.log(this.foo);
}
Base.prototype.doMore = function () {
console.log(this.foo);
}
base = new Base("bar");
base.doStuff();
是否有可能获得第二级,在函数表达式中,“this”关键字指向Base构造函数?
答案 0 :(得分:1)
如果没有原型,这样做会容易得多:
function Base() {
var base = this;
base.level2 = {
moreStuff: function() {
// use "base" instead of "this" here
}
};
}
这可以与原型方法(如您的示例)或构造函数中base
上直接定义的方法结合使用。这样做的缺点是,每次实例化一个新对象时都要创建方法函数,所以你会错过标准原型方法的一些共享原型优点。
您可以创建一个新的基于原型的对象作为您的level2
:
function Level2() {}
Level2.prototype.moreStuff = function() {
// do stuff
}
function Base() {
this.level2 = new Level2();
}
但base.level2
的方法不会绑定到base
,除非您明确绑定它们。各种库都有bind
支持(例如Underscore的_.bind
),或者你可以用普通的JS做到这一点:
function Base() {
var base = this;
base.level2 = new Level2();
base.level2.moreStuff = function() {
return Level2.prototype.moreStuff.apply(base, arguments);
}
}
你可以在这里进一步简化,但是你总是要以这种或那种方式绑定新方法,因为JS永远不会将this
中的base.level2.moreStuff()
分配给{{1}没有显式绑定 - 所以在大多数情况下,第一个选项是最简单和最干净的。
但实际上,仅仅为了命名空间是否值得?如果没有功能价值,那么比简单地调用方法base
等要困难得多。
答案 1 :(得分:0)
那么,
base.doStuff();
在doStuff
的上下文中调用base
。它与
base.doStuff.call(base);
var base = new Base();
var someFun = function () {
console.log (this === base); // true
};
someFun.call(base);
进一步匿名的例子:
var anObj = {
method0: function () {
console.log (this === anObj); // true
}
};
anObj.method1 = function () {
console.log (this === anObj); // true
};
anObj.method0();
anObj.method1();
所以“第二级”将this
指向level2
,而不指向“第一级”对象。
答案 2 :(得分:0)
这是一个非常糟糕的主意,但这里有:
function Base() {
this.name = 'Base';
this.level2 = new Level2(this);
}
Base.prototype.whatsMyName = function(){
alert(this.name);
};
function Level2(base) {
this.name='Level2';
for(var func in Level2.prototype) {
this[func] = Level2.prototype[func].bind(base);
}
}
Level2.prototype.whatsMyName = function(){
alert(this.name);
};
var b = new Base();
b.whatsMyName(); //Base
b.level2.whatsMyName(); //Also Base
您可以在此处看到它:http://jsfiddle.net/zLFgd/1/