关于属性的Javascript原型

时间:2013-09-04 19:15:40

标签: javascript prototype

我想拥有一个具有多级方法和属性的对象。顶级将具有属性和方法。其中一些属性将作为二级方法和属性的名称空间。

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

3 个答案:

答案 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);

您可以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();

所以“第二级”将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/