这是一个简化的例子,展示了我正在努力实现的目标。我正在尝试创建一个类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函数分离?
答案 0 :(得分:3)
你的第一种方法不起作用的原因是你打电话的时候:
在x.say()
say
的正文中,this
会引用x
。
致电时:
x.say.name()
,在name
,this
的正文中,会引用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();