Javascript 每个未定义属性的敲除数组

Javascript 每个未定义属性的敲除数组,javascript,function,knockout.js,Javascript,Function,Knockout.js,我很难从敲除可观察数组中的每个项目中获取一个数字,然后将这些数字相加,然后将其分配给另一个计算变量。这是我现在拥有的 Semesters: ko.observableArray([ { semesterName: "Fall", semesterCode: "300", PlannedCourses: ko.observableArray([]), totalCredits: ko.computed(function(){

我很难从敲除可观察数组中的每个项目中获取一个数字,然后将这些数字相加,然后将其分配给另一个计算变量。这是我现在拥有的

Semesters: ko.observableArray([
    {
        semesterName: "Fall",
        semesterCode: "300",
        PlannedCourses: ko.observableArray([]),
        totalCredits: ko.computed(function(){
            var total = 0;
            ko.utils.arrayForEach(this.PlannedCourses, function (course) {
                total += course.MinHours();
            });

            return total;
        }),
    },
    ...
我要做的是,在totalCredits变量中,我试图迭代PlannedCourses数组,获取每个项目的MinHours变量,并将它们添加到total变量中。然后我将其返回到学期数组中的totalCredits项。我遇到的问题是在ko.utils.arrayForEach部分中获取PlannedCourses变量。我得到了一个未定义的关于它,我不知道为什么。我认为这是一个简单的语法错误,但我看不出有什么错

PlannedCourses可观测数组是一个动态对象,可以正确获取PlannedCourses列表。它是在自身的上下文中定义的,但我没有正确地将其传递给totalCredits计算函数

我希望这足够清楚。谢谢你的帮助


注意:代码的所有其余部分都按预期工作。唯一不起作用的部分是totalCredits计算函数。我不确定ko.utils.arrayForEach中的任何内容是否正常工作,因为我还没有做到这一点。

这个范围不是您所认为的范围

尝试添加您的上下文,如下所示:

Semesters: ko.observableArray([
{
    semesterName: "Fall",
    semesterCode: "300",
    PlannedCourses: ko.observableArray([]),
    totalCredits: ko.computed(function(){
        var total = 0;
        ko.utils.arrayForEach(this.PlannedCourses, function (course) {
            total += course.MinHours();
        });

        return total;
    }, this), // new context passed in here
},
...
这样做会将数组项本身的上下文传递到计算函数中

编辑: 您可能需要访问循环中的Semesters对象,并添加一些方法来引用当前项:

Semesters: ko.observableArray([
{
    semesterName: "Fall",
    semesterCode: "300",
    PlannedCourses: ko.observableArray([]),
    totalCredits: ko.computed(function(){
        var total = 0;
        for( var i = 0, len = Semesters().length; i < len; i++ ) {
            // check current array item, possibly add an id?
            if( Semesters()[i].semesterName === "Fall" &&
                Semesters()[i].semesterCode === "300" ) {

                ko.utils.arrayForEach(Semesters()[i].PlannedCourses, function (course) {
                   total += course.MinHours();
                });
                break; // done searching
            }
        }

        return total;
    })
},

这个范围不是你想象的那样

尝试添加您的上下文,如下所示:

Semesters: ko.observableArray([
{
    semesterName: "Fall",
    semesterCode: "300",
    PlannedCourses: ko.observableArray([]),
    totalCredits: ko.computed(function(){
        var total = 0;
        ko.utils.arrayForEach(this.PlannedCourses, function (course) {
            total += course.MinHours();
        });

        return total;
    }, this), // new context passed in here
},
...
这样做会将数组项本身的上下文传递到计算函数中

编辑: 您可能需要访问循环中的Semesters对象,并添加一些方法来引用当前项:

Semesters: ko.observableArray([
{
    semesterName: "Fall",
    semesterCode: "300",
    PlannedCourses: ko.observableArray([]),
    totalCredits: ko.computed(function(){
        var total = 0;
        for( var i = 0, len = Semesters().length; i < len; i++ ) {
            // check current array item, possibly add an id?
            if( Semesters()[i].semesterName === "Fall" &&
                Semesters()[i].semesterCode === "300" ) {

                ko.utils.arrayForEach(Semesters()[i].PlannedCourses, function (course) {
                   total += course.MinHours();
                });
                break; // done searching
            }
        }

        return total;
    })
},

正如其他人已经提到的,这不是你所认为的。在您的情况下,应将上下文传递给计算对象,如下所示:

totalCredits: ko.computed(function() {
    // Computation goes here..
}, this)
另一种方法是在对象创建期间将正确的this存储到某个局部变量,例如var self=this;然后用self代替这个


但是,ko.utils.arrayForEach不适用于可观察数组,而适用于纯JavaScript数组,因此您应该展开可观察数组以访问底层数组的元素:

ko.utils.arrayForEach(this.PlannedCourses(), function(course) { 
    // ...
});

// Or

ko.utils.arrayForEach(ko.unwrap(this.PlannedCourses), function(course) { 
    // ... 
});

正如其他人已经提到的,这不是你所认为的。在您的情况下,应将上下文传递给计算对象,如下所示:

totalCredits: ko.computed(function() {
    // Computation goes here..
}, this)
另一种方法是在对象创建期间将正确的this存储到某个局部变量,例如var self=this;然后用self代替这个


但是,ko.utils.arrayForEach不适用于可观察数组,而适用于纯JavaScript数组,因此您应该展开可观察数组以访问底层数组的元素:

ko.utils.arrayForEach(this.PlannedCourses(), function(course) { 
    // ...
});

// Or

ko.utils.arrayForEach(ko.unwrap(this.PlannedCourses), function(course) { 
    // ... 
});

您需要更改填充学期可观察数组的方式,以使用构造函数,从而获得对正确范围的引用:

看看我们现在如何将对象传递给ko.computed的第二个参数,以便在内部函数中将其用作上下文。有关更多信息,请参阅淘汰文档:

然后,在填充数组时创建新的实例:

Semesters: ko.observableArray([
    new semester("Fall", "300"),
    new semester(...)
]);

这种方法也意味着你有一种一致的方法来创建你的学期对象,计算只定义一次,您需要改变填充学期可观察数组的方式,以使用构造函数,从而获得对正确范围的引用,而不是在您最初的任何重复中加入拼写错误等。

看看我们现在如何将对象传递给ko.computed的第二个参数,以便在内部函数中将其用作上下文。有关更多信息,请参阅淘汰文档:

然后,在填充数组时创建新的实例:

Semesters: ko.observableArray([
    new semester("Fall", "300"),
    new semester(...)
]);

这种方法还意味着你有一种一致的方法来创建你的学期对象。计算只为一件事定义一次,而不可能在你最初可能有的任何重复中包含打字错误等。

以对象的构造方式,这在外部范围内也不是正确的事情。@JamesThorpe我的想法很正确,它看起来@JomesThorpe是正确的。我对计划课程还没有定义。我百分之百肯定它也在计划中。当注释掉totalCredits的计算函数时,未定义的错误消失。在控制台中,当我查看:da.vm.Years[0].Semesters[0].PlannedCourses时,我得到了PlannedCourses数组中预期的对象列表。所以列表正在填充…@JoshSalazar,我想你需要一个基于根学期数组的查找。检查我的edit@JoshSalazar虽然这可能有效,但我真的建议你不要长期采用这种方法
rm。使用JavaScript及其作用域的工作方式。按照对象的构造方式,这在外部作用域上也不是正确的事情。@JamesThorpe我的想法是正确的@JomesThorpe似乎是正确的。我对计划课程还没有定义。我百分之百肯定它也在计划中。当注释掉totalCredits的计算函数时,未定义的错误消失。在控制台中,当我查看:da.vm.Years[0].Semesters[0].PlannedCourses时,我得到了PlannedCourses数组中预期的对象列表。所以列表正在填充…@JoshSalazar,我想你需要一个基于根学期数组的查找。检查我的edit@JoshSalazar虽然这可能有效,但我真的建议你不要长期采用这种方法。使用JavaScript及其作用域的工作方式。但是,ko.utils.arrayForEach不使用可观察数组,而是使用纯JavaScript数组,我不知道这一点。非常感谢。我已经编辑了我的代码以使用ko.unwrap,并将self分配给了它。不过,我对计划的课程还没有定义。让我再看一眼,看看是否能找出我的错误范围之外的情况……但是,ko.utils.arrayForEach不适用于可观察数组,而是适用于我不知道的纯JavaScript数组。非常感谢。我已经编辑了我的代码以使用ko.unwrap,并将self分配给了它。不过,我对计划的课程还没有定义。让我再看一看,看看我是否能找出我的错误范围之外的情况……这可能是最好的方法。我将不得不进行大量重组,但毫无疑问我应该这样做。我很感激。我正在尝试合并两种不同的viewModel方法,这会使事情变得复杂。现在,学期是另一系列年的一部分,这些年的学术工作和学期的结构与学期大致相同。如果我按照您指定的方式修改这两个列表,这应该会起作用。不过,这需要一些时间。如果这有效的话,我会尽快给你回复。再次感谢!如果要创建具有相同属性/函数等的多个对象,这将是常用的方法这可能是最好的方法。我将不得不进行大量重组,但毫无疑问我应该这样做。我很感激。我正在尝试合并两种不同的viewModel方法,这会使事情变得复杂。现在,学期是另一系列年的一部分,这些年的学术工作和学期的结构与学期大致相同。如果我按照您指定的方式修改这两个列表,这应该会起作用。不过,这需要一些时间。如果这有效的话,我会尽快给你回复。再次感谢!如果要创建具有相同属性/函数等的多个对象,这将是通常的方法