2

我正在试验淘汰赛和映射插件,想知道为什么这不起作用。我有一个要使用映射扩展加载的视图模型

function todoListViewModel(data) {
    ko.mapping.fromJSON(data, { todos: TodoItem.options }, self);
    ko.mapping.fromJSON(data, { todos: TodoItem.options }, self);
}

映射有一个看起来像这样的选项:

    var TodoItem = function (options) {
        var todoItem = ko.mapping.fromJS(options.data);

        todoItem.remove = function () {
            alert('remove');
        };

        return todoItem;
    };
    TodoItem.options = {
            create: TodoItem 
    };

JSON 数据如下所示:

{
    "id": "0",
    "todo": "",
    "todos": [
        {
            "todo": "Kevin",
            "isDone": true
        }
    ]
}

对映射的第一次调用成功,但第二次调用失败并出现堆栈溢出:(Chrome 中的“未捕获 RangeError:超出最大调用堆栈大小”)

如果我更改代码以便不将选项传递给映射,则不会引发异常。

我也尝试过将 ToDo 构造函数简化为此

var TodoItem = function (options) {
    var todoItem = {};

    return todoItem;
};

但我仍然得到同样的错误。

看起来我不能这样做,但我想知道为什么?

4

1 回答 1

3

问题在于这一点:

TodoItem.options = {
    create: TodoItem 
};

您正在使用属性“选项”扩展 TodoItem,该属性再次包含 TodoItem - 因此函数 TodoItem 具有包含自身的属性。

TodoItem.options.create == TodoItem
TodoItem.options.create.options.create == TodoItem
TodoItem.options.create.options.create.options.create == TodoItem
...

因为它只是一个参考,所以这在 JavaScript 中没有问题。但是淘汰映射插件似乎对该选项对象执行了一些复制操作(或具有相同效果的操作),即它尝试迭代其所有属性并因此以无限循环结束。

您可以通过使用匿名函数作为包装器轻松解决此问题:

TodoItem.options = {
    create: function(options) {
        return new TodoItem(options);
    }
};
于 2012-06-16T08:57:43.607 回答