我正在尝试更熟悉Javascript OOP,因此我编写了一个小测试脚本,但在测试时我一直遇到异常:
例外:
Uncaught TypeError: Cannot call method 'day' of undefined
代码:
(function () {
function Time (date) {
var self = this;
var timeInWeek = 604800000;
var timeInDay = 86400000;
var dateInMilliSeconds = date.getTime();
self.add = function (num) {
self.day = function () {
var newDate = new Date();
newDate.setTime(dateInMilliSeconds + (timeInDay * num));
return newDate;
};
};
};
var date = new Date();
var time = new Time(date).add(1).day();
console.log(time);
})();
当我在IIFE模式之外运行测试脚本时,我得到异常Time is undefined
,我是Javascript OOP的新手,所以当我尝试阅读其他Javascript库时,我的头脑中有一大块。任何帮助表示赞赏。
答案 0 :(得分:4)
add
方法返回undefined,因为它没有return
语句。这个问题与IIFE的使用无关。
相反,add
方法在执行时只添加(可能覆盖)day
方法,因此以下内容将“有效”:
var time = new Time(date)
t.add(1); // returns undefined, but has a side-effect of adding "day" to t
t.day();
但是,我怀疑这个问题是双重的:
add
应该return
Method Chaining兼容类型的对象;这可以是同一个对象(对于可变设计),也可以是新对象(对于不可变设计)。
day
应直接添加到每个Time对象;这会使new Time(date).day()
能够正常工作。
例如:
function Time (date) {
var self = this;
var timeInWeek = 604800000;
var timeInDay = 86400000;
var dateInMilliSeconds = date.getTime();
self.add = function (num) {
// The idea here is to return an object of the same type for "chaining".
// Here I returned a new Time object (you'll have to work out the details),
// although for mutable objects, "return self" would be appropriate.
return new Time(dateInMilliSeconds + (timeInDay * num));
};
self.day = function () {
// actually return the "day", whatever that is.
return ...;
};
};
虽然这可能是一个很好的练习,但对于生产代码,我建议使用moment.js,除非有其他令人信服的理由。 moment.js的源代码(可能是一个很好的参考)在github/moment上。 “添加”(带有遗漏和附加注释)如下所示:
add : function (input, val) {
// mutate this objects data (but not methods)
addOrSubtractDurationFromMoment(this, dur, 1);
// returns the same object for chaining
return this;
},
答案 1 :(得分:3)
你错过了一个return this;
(必须在那里允许菊花链接)
function Time (date) {
var self = this;
var timeInWeek = 604800000;
var timeInDay = 86400000;
var dateInMilliSeconds = date.getTime();
self.add = function (num) {
self.day = function () {
var newDate = new Date();
newDate.setTime(dateInMilliSeconds + (timeInDay * num));
return newDate;
};
return this; //this
};
};
如果没有return
语句,则在new Time(date).add(1).day())
中day()
被视为add
实例的new Time()
方法返回的值的方法。如果add
方法未返回具有day
方法的对象,则您肯定会收到错误。
只有链接才需要return this
。
您的代码可以正常使用
var time = new Time(date);
time.add(1);
time.day();
OR
var time = new Time(date).add(1);
time.day()