如何在类中解耦嵌套对象函数

时间:2013-10-10 15:21:57

标签: javascript node.js prototype

背景

这是一个简化的例子,展示了我正在努力实现的目标。我正在尝试创建一个类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; }
    });
};

但输出仍然相同。

什么有效

的工作是将say对象嵌套在Person函数中:

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函数分离?

2 个答案:

答案 0 :(得分: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();

DEMO:http://jsbin.com/OPuveGA/1/edit

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

答案 1 :(得分: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();