1

背景

这是一个简化的示例,演示了我要完成的工作。我正在尝试创建一个类Person(name)。这个类有一个对象say,它有几个与之关联的函数,例如

Person.say.name();

调用时,这应该输出My name is (name provided)

简单的工作示例

// node v0.10.15
var Person = function(name) {
    this.name = name;
};

Person.prototype.greet = function() {
    console.log('Hello ' + this.name);
};

Person.prototype.say = function() {
    var self = this;
    this.say = {
        name: function() {
            console.log('My name is ' + self.name);
        }
    };
};

Person.prototype.say();

var p = new Person('Nolan');
p.greet();
p.say.name();

以上将输出

Hello Nolan 
My name is undefined

我试过的

我试过使用bind

Person.prototype.say = function() {
    var name = function() {
        console.log('My name is ' + this.name);
    };
    this.say = {};
    this.say.name = name.bind(this);
};

我还尝试在 Person 函数中使用defineProperty :

var Person = function(name) {
    Object.defineProperty(this, 'name', {
        get: function() { return name; }
    });
};

但输出保持不变。

什么有效

起作用的是将对象嵌套在Personsay函数中:

var Person = function(name) {
    this.name = name;
    var self = this;
    this.say = {
        name: function() {
            console.log('My name is ' + self.name);
        }
    };
};

但这是我试图避免的,因为该say对象可能包含更多的功能name()(例如年龄、电子邮件等),并且主要的 Person 功能会变得臃肿。

问题

如何将say对象与主要的 Person 函数分离?

4

2 回答 2

3

您的第一种方法不起作用的原因是,当您调用 : 时 x.say(),内部say this将引用x.

当你调用: x.say.name()时,在 的体内namethis将引用x.say

为了x.say.name()给出正确答案,x.say应该有参考x。因此,在您的构造函数中,您需要将say对象与新实例链接起来(这就是嵌套事物起作用的原因)。

可以这样进行更好的分离:

Sayer = function(person){
  this.person = person;
};
Sayer.prototype.name = function() {
    console.log('My name is ' + this.person.name);    
};

var Person = function(name) {
    this.name = name;
    this.say = new Sayer(this);
};

Person.prototype.greet = function() {
    console.log('Hello ' + this.name);
};

p = new Person('George');
p.say.name();

演示:http: //jsbin.com/OPuveGA/1/edit

PS:显然,您可以在任何您想要的命名空间中定义 Sayer 构造函数,包括 Person,因此您可以this.say = new Person.Sayer(this)在您的 Person 构造函数中拥有 - 检查上面的演示。

于 2013-10-10T15:50:03.180 回答
2

不确定这是否是您的想法:

// node v0.10.15
var Person = function(name) {
    this.name = name;
    this.say = new Person.prototype.say(name);
};

Person.prototype.greet = function() {
    console.log('Hello ' + this.name);
};

Person.prototype.say = function(moniker) {
    this.moniker = moniker;
    this.name =  function() {
            console.log('My name is ' + moniker);
        };
};

Person.prototype.say();

var p = new Person('Nolan');
p.greet();
p.say.name();
于 2013-10-10T15:32:47.790 回答