在Javascript OOP中调用嵌套函数

时间:2013-12-04 19:10:13

标签: javascript oop

我正在尝试更熟悉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库时,我的头脑中有一大块。任何帮助表示赞赏。

2 个答案:

答案 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();     

但是,我怀疑这个问题是双重的:

  1. add应该return Method Chaining兼容类型的对象;这可以是同一个对象(对于可变设计),也可以是新对象(对于不可变设计)。

  2. day应直接添加到每个Time对象;这会使new Time(date).day()能够正常工作。

  3. 例如:

    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()