0

我想要一个具有多级方法和属性的对象。顶层将具有属性和方法。然后,其中一些属性将充当二级方法和属性的名称空间。

例如

//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 构造函数?

4

3 回答 3

1

It's much easier to do this without prototypes:

function Base() {
    var base = this;
    base.level2 = {
        moreStuff: function() {
            // use "base" instead of "this" here
        }
    };
}

This can be combined with either prototypical methods, as in your example, or methods defined directly on base in the constructor. The downside of this is that you are creating the method functions every time you instantiate a new object, so you miss some of the shared-prototype goodness of standard prototypical methods.

You could create a new prototype-based object to be your level2:

function Level2() {}
Level2.prototype.moreStuff = function() {
    // do stuff
}

function Base() {
    this.level2 = new Level2();
}

But the methods of base.level2 won't be bound to base unless you bind them explicitly. Various libraries have bind support (e.g. Underscore's _.bind), or you can do it in plain JS:

function Base() {
    var base = this;
    base.level2 = new Level2();
    base.level2.moreStuff = function() {
        return Level2.prototype.moreStuff.apply(base, arguments);
    }
}

You could further simplify here, but you're always going to have to make new methods bound in one way or another, because JS is never going to assign this in base.level2.moreStuff() to base without explicit binding - so in most cases the first option is the easiest and cleanest.

But really, is it worthwhile just for namespacing? If there's no functional value, it's a lot harder than simply calling your methods level2MoreStuff(), etc.

于 2013-09-04T19:50:41.660 回答
0

出色地,

base.doStuff();

doStuff在 的上下文中调用base。它与

base.doStuff.call(base);

您可以使用任何功能callapply覆盖this

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();

所以“第二级”指向thislevel2而不是“第一级”对象。

于 2013-09-04T19:27:13.033 回答
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/

于 2013-09-04T20:02:51.630 回答