Javascript 检查对象是否已定义,最佳实践。
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3954630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if a object is defined, best practice.
提问by nekman
I have the following JSON response from a ajax-request.
我有来自 ajax 请求的以下 JSON 响应。
var json = {
"response": {
"freeOfChargeProduct": {
"description": "Product",
"orderQty": 5,
"productName": "XYZ",
"qty": 6,
"details": {
"price": 55.5,
"instock": "true",
"focQuantity": 1
}
},
"orderLineId": 4788,
"totalOrderLinePrice": "741.36",
"totalOrderPrice": "1,314.92",
"totalQty": 17
};
The JSON dosen't always return a "freeOfChargeProduct" property. So if I want to get the "freeOfChargeProduct" price, then I have to do the following:
JSON 并不总是返回“freeOfChargeProduct”属性。因此,如果我想获得“freeOfChargeProduct”价格,那么我必须执行以下操作:
var getFreeOfChargeProductPrice = function() {
var r = json.response;
if (r && r.freeOfChargeProduct && r.freeOfChargeProduct.details) {
return r.freeOfChargeProduct.details.price;
}
return null;
};
No problems. But it's very annoying to check every property in the object, so I created a function that check if a property in a object is defined.
没问题。但是检查对象中的每个属性很烦人,所以我创建了一个函数来检查对象中的属性是否已定义。
var getValue = function (str, context) {
var scope = context || window,
properties = str.split('.'), i;
for(i = 0; i < properties.length; i++) {
if (!scope[properties[i]]) {
return null;
}
scope = scope[properties[i]];
}
return scope;
};
var price = getValue('json.response.freeOfChargeProduct.details.price');
// Price is null if no such object exists.
Now to my question: Is this a good or bad way to check if a property exists in an object? Any better suggestions/methods?
现在我的问题是:这是检查对象中是否存在属性的好方法还是坏方法?有什么更好的建议/方法吗?
EDIT:
编辑:
I don't wan't to use the &&-operator. I am lazy and I'm looking for a reusable method to check if a object (or property of a object) is defined.
我不想使用 && 运算符。我很懒,我正在寻找一种可重用的方法来检查是否定义了对象(或对象的属性)。
:) Thanks!
:) 谢谢!
采纳答案by PleaseStand
if(x && typeof x.y != 'undefined') {
...
}
// or better
function isDefined(x) {
var undefined;
return x !== undefined;
}
if(x && isDefined(x.y)) {
...
}
This will work for any data type in JavaScript, even a number that is zero. If you are checking for an object or string, just use x && x.y
within the if statement, or if you already know that x is an object, if(x.y) ...
这适用于 JavaScript 中的任何数据类型,甚至是零数字。如果您正在检查一个对象或字符串,只需x && x.y
在 if 语句中使用,或者如果您已经知道 x 是一个对象,if(x.y) ...
回答by ?ime Vidas
Use the guard pattern:
使用保护模式:
if (json.response && json.response.freeOfChargeProduct && json.response.freeOfChargeProduct.details) {
// you can safely access the price
}
This is how the guard pattern works.
这就是保护模式的工作原理。
if (a && a.b && a.b.c) { ... } else { ... }
The first check is "Does the property a
exist?". If not, the else-branch gets executed. If yes, then the next check occurs, which is "Does object a
contain the property b
?". If no, the else-branch executes. If yes, the final check occurs: "Does the object a.b
contain the property c
?". If no, the else-branch executes. If yes (and only then), the if-branch executes.
第一个检查是“该财产是否a
存在?”。如果没有,则执行 else 分支。如果是,则进行下一个检查,即“对象是否a
包含该属性b
?”。如果不是,则执行 else 分支。如果是,则进行最后的检查:“对象是否a.b
包含属性c
?”。如果不是,则执行 else 分支。如果是(并且只有这样),则执行 if 分支。
Update: Why is it called "guard pattern"?
更新:为什么叫“守卫模式”?
var value = a && b;
In this example, the member b
(the right operand) is guarded by the &&
operator. Only if the member a
(the left operand) is truthy ("worthy"), only then the member b
is returned. If, however, the member a
is falsy ("not worthy"), then it itself is returned.
在这个例子中,成员b
(右操作数)由&&
操作符保护。仅当成员a
(左操作数)为真(“值得”)时,才b
返回该成员。但是,如果该成员a
为假(“不值得”),则返回它本身。
BTW, members are falsy if they return these values: null
, undefined
, 0
, ""
, false
, NaN
. Members are truthy in all other cases.
顺便说一句,如果成员返回以下值,则成员为假:null
, undefined
, 0
, ""
, false
, NaN
。成员在所有其他情况下都是真实的。
回答by Frank
You could do something like this:
你可以这样做:
try{
var focp = json.response.freeOfChargeProduct
var text = "You get " + focp.qty + " of " +
focp.productName +
" for only $" + (focp.qty-focp.details.focQuantity)*focp.details.price +
", You save $" + focp.details.focQuantity*focp.details.price;
$("order_info").innerText = text;
} catch(e) {
// woops, handle error...
}
It would generate a message like this from the provided data in your question if the fields exists:
如果这些字段存在,它会根据您问题中提供的数据生成这样的消息:
You get 6 of XYZ for only $277,5, You save $55.5
您只需 277.5 美元即可获得 6 个 XYZ,您节省 55.5 美元
If the data is non-existing, you'll end up in the catch block. You could always just to a Try, Catch, Forget here if you can't come up with a way to handle the error (Maybe do a new AJAX request for the data?).
如果数据不存在,您将在 catch 块中结束。如果您无法想出处理错误的方法(也许对数据执行新的 AJAX 请求?),您可以随时尝试、捕获、忘记这里。
回答by Demas Sinner
This is not a syntax issue as it is a design pattern issue.
这不是语法问题,因为它是设计模式问题。
Question A. * Do you have control of the json server?
问题 A. * 您是否可以控制 json 服务器?
If the answer to this is no, which I assume, the situation will be all on the client.
如果对此的答案是否定的,我认为,情况将全部由客户承担。
Please read this: http://martinfowler.com/eaaDev/PresentationModel.html
请阅读:http: //martinfowler.com/eaaDev/PresentationModel.html
As the server is the source, in this case it will provide the model. This pattern specifies an additional artifact: The presentation model (PM). In javascript i would suggest two artifacts, a additional for the convertor code.
由于服务器是源,在这种情况下它将提供模型。此模式指定了一个额外的工件:表示模型 (PM)。在 javascript 中,我建议使用两个工件,一个用于转换器代码的附加工件。
According to this design pattern the PM is responsible for converting the model to the PM, and back again if necessary. In your case no conversion from PM to M will ever occur.
根据这种设计模式,PM 负责将模型转换为 PM,必要时再返回。在您的情况下,不会发生从 PM 到 M 的转换。
This means that a js object has a method or constructor that digest the model and translate itself, with the help of the convertor (below).
这意味着 js 对象有一个方法或构造函数,可以在转换器的帮助下消化模型并自行翻译(见下文)。
Doing this you will end up with a PM looking like this:
这样做你最终会得到一个像这样的 PM:
var OrderlinePM = {
"hasFreeOfCharge": false | true,
"freeOfCharge" : {...}
`enter code here`
this.getFreeOfCharge = function() {
...
}
this.fromModel = function(jsonEntry, convertor) {
//convert this with the convertor ;) to a for this specific view usable OrderlinePM
// also inwith
...
}
enter code here
"orderLineId":0,
"totalOrderLinePrice":"741.36",
"totalOrderPrice":"1,314.92",
"totalQty":17
};
function mySpecialFunctionPMConvertor {
this.fromModel = function() {
... //do strange stuff with the model and poulate a PM with it.
}
}
Ok, I give up trying to format code in this rich text editor :(
好的,我放弃了在这个富文本编辑器中格式化代码的尝试:(
- You can have several PM:s for diffrent tasks all depending on the same model object.
- In addition this will make the converter object testable in something that could be automatically executed.... err ok maby manually, but anyway.
- 您可以有多个 PM:s 用于不同的任务,所有这些都取决于相同的模型对象。
- 此外,这将使转换器对象可以在可以自动执行的东西中进行测试.... 手动错误,但无论如何。
So the problem of the cumbersome reflection code is really not a problem. But cohesion is a issue, expessially in JavaScript.
所以繁琐的反射代码的问题真的不是问题。但是内聚是一个问题,尤其是在 JavaScript 中。