2017-04-19 69 views
3

在我的nodejs程序中,我有一个叫做person的模块,它有一个也有它的子方法(describe)的原型对象(about)。我试图访问对象的属性,但我越来越未定义。nodejs中的递归原型继承/ javascript

有人能纠正我的理解吗?我在这里做错了什么?

index.js

var Person = require("./person"); 
var sam = new Person({name:"Sam",age:23}) 
sam.about.describe(); 

person.js

module.exports = (function() { 
    var person = function(options) { 
     if (options && options.name) this.name = options.name; 
     if (options && options.age) this.age = options.age; 
    } 
    person.prototype.about = { 
     describe : function(){ 
      console.log("I am",this.name,"and",this.age,"years old"); 
     } 
    } 
    return person; 
})(); 

预期输出: “我是萨姆和23岁的” 实际输出: “我是不确定的,不确定岁”

+0

那是因为'this'指向'about'而不是'person'。在原型中也有对象会产生副作用 – Rajesh

+0

这里的递归是什么? – 2017-04-19 11:12:21

+0

@torazaburo ..对不起,它实际上并没有递归..将修改.. –

回答

1

正如其他人所说的,您示例中的this引用about对象,而不是person实例本身。

获得所需API的一种方法是在构造函数中创建about名称空间,并使用bind将正确的上下文设置为describe处理程序。

module.exports = (function() { 
    var person = function(options) { 
     if (options && options.name) this.name = options.name; 
     if (options && options.age) this.age = options.age; 
     this.about = { 
      describe: function() { 
       console.log("I am",this.name,"and",this.age,"years old"); 
      }.bind(this) 
     }; 
    } 

    return person; 
})(); 

这样,你可以简单地调用

var Person = require("./person"); 
var sam = new Person({name:"Sam",age:23}) 
sam.about.describe(); 

>>> I am Sam and 23 years old 
1

这是因为this指的是describe的直接父项,即about

person.prototype.about = { 
     describe : function() { 
      console.log("I am",this.name,"and",this.age,"years old"); 
     } 
} 

你需要一个弱引用传递给about命名空间例如主Person对象,并在地方this使用它。但是我不喜欢那种方式,它是迂回的,感觉不对的,看起来很臭。

相反,我们只是aknowledge的事实,这是一个完全新的功能包添加到Person对象,并让我们为它帮手:

module.exports = (function() { 
    var PersonHelper = function(person) { 
     this.person = person; 
     describePerson: function() { 
      console.log("I am",this.person.name,"and",this.person.age,"years old"); 
     } 
     /* more methods */ 
    } 
    return PersonHelper; 
})(); 

所以,你可以那么做:

module.exports = (function() { 
    var person = function(options) { 
     if (options && options.name) this.name = options.name; 
     if (options && options.age) this.age = options.age; 
    } 
    return person; 
})(); 


var Person = require("./person"); 
var PersonHelper = require("./personHelper"); 
var sam = new Person({name:"Sam",age:23}) 
var helper = new PersonHelper(person); 
helper.describePerson(); 
+0

像通过山姆通过描述方法?萨姆。about.describe(SAM);然后描述:function(user){console.log(“我是”,user.name,“和”,user.age,“years old”); } –

+0

是的,这将工作,但它有点难看。也许你最好一起使用PersonH​​elper对象,它会嵌入像describe等函数。让我把它放在答案上。 – Sebas

0

如果你真的想能够使用sam.about.describe,与about“命名空间”包含方法,则一种方法是

Object.defineProperty(person.prototype, 'about', { 
    get() { 
    return { 
     describe:() => console.log("I am", this.name, "and", this.age, "years old"); 
    }; 
    } 
}) 

这是可行的,因为get中的上下文是Person实例的上下文,因此箭头函数将正确引用它。

+0

但根据我的要求,我需要“关于”名称空间,其中包含多个函数,如“描述” –