knockout computed函数 - 无法读取null的属性'price'

时间:2013-07-18 09:03:16

标签: knockout.js

我正在尝试访问对象的属性,我知道该对象存在(并且具有我需要的属性),因为我可以将其记录到控制台。

然而,当我尝试访问它时,它说无法读取null的属性'price'。

我是一名C#开发人员并且很困惑我必须做错事但我不知道是什么?从我的屏幕截图中,您可以看到返回的对象。

我的代码如下:

self.total = ko.computed(function(){
    var total = 0;      
    var selectedServerName = this.selectedServer();
    var selectedServerObject = ko.utils.arrayFirst(this.server, function(server){
        console.log("server.name = " + server.name);
        console.log("selectedServerName = " + selectedServerName);
        var serverCompare = (server.name == this.selectedServer());
        console.log("serverCompare is " + serverCompare);
    }, this);

    var selectedOsName = this.selectedOs();
    var selectedOsObject = ko.utils.arrayFirst(this.os, function(os){
        console.log("os.name = " + os.name);
        console.log("selectedOsName = " + selectedOsName);
        var osCompare = (os.name == this.selectedServer());
        console.log("osCompare is " + osCompare);
    }, this);

    total = total + selectedServerObject.price + selectedOsObject.price;

    return total;
},this);

更新

我的更新小提琴在这里:fiddle here

感谢d.raev,当第二个日志行被添加console.log(selectedServerObject.price时,会出现使用selectedServer = undefined调用arrayFirst函数。

server.name = DELL R210
selectedServerName = undefined
serverCompare is false
server.name = DELL R710
selectedServerName = undefined
serverCompare is false
server.name = DELL R720 Dual CPU
selectedServerName = undefined
serverCompare is false
os.name = Windows Standard
selectedOsName = undefined
osCompare is false
os.name = Windows Enterprise
selectedOsName = undefined
osCompare is false
os.name = CentOS Linux
selectedOsName = undefined
osCompare is false
os.name = Debian
selectedOsName = undefined
osCompare is false
1.  Uncaught TypeError: Cannot read property 'price' of null 

来自selectedOsName或selectedServerName的未定义值导致总计失败,它们被设置为未定义的原因是什么?

2 个答案:

答案 0 :(得分:2)

你的脚本运行2次这个函数,添加第二个调试显示它更清晰:

var selectedServerObject = ko.utils.arrayFirst(this.server, function(server){
    console.log("server.name = " + server.name);
    console.log("selectedServer = " + this.selectedServer());
    return server.name ==  this.selectedServer();
}, this); 

输出:


server.name = DELL R210
selectedServer = undefined
server.name = DELL R710
selectedServer = undefined
server.name = DELL R720双CPU
selectedServer = undefined
null (selectedServerObject)
...
server.name = DELL R210
selectedServer = DELL R210
对象{名称:“DELL R210”,规格:“1 x 2.4GHz四核CPU 4GB RAM
2 x 300GB SAS 15k”,价格:100}


如果设置了selectedServerObject,只需添加一个检查..或者找到它被调用2次的原因:

示例:

if(selectedServerObject){
   total = total + selectedServerObject.price;
}

答案 1 :(得分:0)

这里的小提琴http://jsfiddle.net/g18c/2SAxR/2/显示d.raev的怀疑是正确的:)我已经创建了我的原始代码的精简版本,当selectedServer未定义时调用描述计算函数,导致所有内容爆炸

我已将d.raev的回复标记为答案,因为它找到了根本原因 - 了解完全关闭的敲击行为会很好。

<div data-bind="foreach: server">
    <div>
        <input type="radio" name="server" data-bind="attr: {value: sku}, checked: $root.selectedServer" />
        <span data-bind="text: name"></span>
    </div>
</div>
<p data-bind="text: selectedServer"></p>
<p data-bind="text: description"></p>

var serverOptions = [{
    name: "One",
    sku: 1000,
    specification: "yes",
    price: 100
}, {
    name: "Two",
    sku: 1001,
    specification: "hello",
    price: 200
}, {
    name: "Three",
    sku: 1002,
    specification: "wow",
    price: 300
}];

viewModel = function() {
    var self = this;
    self.server = serverOptions;
    self.selectedServer = ko.observable();
    self.description = ko.computed(function () {
        var selectedSku = this.selectedServer();
        if(typeof selectedSku == "undefined")
        {
            console.log("we are not fully bound, bombing out here...");
            return;
        }

        var found = ko.utils.arrayFirst(serverOptions, function (item) {
            var result = (item.sku == selectedSku);
            console.log("arrayFirst check => item.sku = " + item.sku + " selectedSku = " + selectedSku + ". result = " + result );
            return result;
        }, this);

        var textDescription = found.name + " - " + found.specification + " (" + found.price + ")";

        return textDescription;
    }, this);

    return self;
};

ko.applyBindings(new viewModel());