Advice on using hasOwnProperty

Hello

I need to check if a payload property exists. The payload looks like this:

image

The path to that payload object is payload.data.dps["5"]

Sometimes element 5 is not present. How do I check if element 5 exists in this payload with hasOwnProperty?

Hi,

With:

Object.prototype.hasOwnProperty.call(msg.payload.data.dps, "5");
1 Like

Thank you!

Or

msg.payload.data.dps.hasOwnProperty("5")

The difference being you can use nullish Coalescing optional chaining.

msg.payload?.data?.dps?.hasOwnProperty("5")

There is a reason to use the form that GogoVega has used. Can't remember the details but it is the safest way to do it.

However, there is a still newer method:

This is intended to replace hasOwnProperty and it should be safe to use directly. It correctly identifies properties set to null or undefined and it ignores properties inherited from the object prototype.

Note however that you must be using node.js v16.9.0 or above to use hasOwn.

1 Like

Because of Object.create() - the risk is that property does not exist or has been rewritten.
There are other more purist reasons but that's not my area

1 Like

hasOwn() still has issues if a previous property is undefined, that is why I pointed out the other way and use of nullish coalescing optional chaining.

example

[{"id":"67945dd7ba95413d","type":"inject","z":"d1395164b4eec73e","name":"index 4","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":[1,2,3,4,5]}}","payloadType":"json","x":970,"y":2360,"wires":[["7132475e275fd915"]]},{"id":"7132475e275fd915","type":"function","z":"d1395164b4eec73e","name":"has own or has ownproperty","func":"if (!Object.hasOwn(msg.payload.data.dps, 5)){\n    msg.payload = {data:{dps:[1,2,3,4,5,6]}};\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1180,"y":2360,"wires":[["9bff22b548d19bc2"]]},{"id":"9bff22b548d19bc2","type":"debug","z":"d1395164b4eec73e","name":"debug 2461","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1310,"y":2360,"wires":[]},{"id":"6f4fee8e626dc95d","type":"inject","z":"d1395164b4eec73e","name":"index 5","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":[1,2,3,4,5,6]}}","payloadType":"json","x":970,"y":2420,"wires":[["7132475e275fd915"]]},{"id":"c0da96b3db8a23a7","type":"inject","z":"d1395164b4eec73e","name":"no dps","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{}}","payloadType":"json","x":970,"y":2480,"wires":[["7132475e275fd915"]]},{"id":"abe99dd5257e8f27","type":"inject","z":"d1395164b4eec73e","name":"index 4","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":[1,2,3,4,5]}}","payloadType":"json","x":950,"y":2520,"wires":[["c0039a0b6001719d"]]},{"id":"c0039a0b6001719d","type":"function","z":"d1395164b4eec73e","name":"hsa OwnPropert with nullish","func":"if (!msg.payload.data.dps?.hasOwnProperty(5)){\n    msg.payload = {data:{dps:[1,2,3,4,5,6]}};\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1160,"y":2520,"wires":[["b85dcf65125b7a8a"]]},{"id":"b85dcf65125b7a8a","type":"debug","z":"d1395164b4eec73e","name":"debug 2462","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1290,"y":2520,"wires":[]},{"id":"2c13e340cd6cebf6","type":"inject","z":"d1395164b4eec73e","name":"index 5","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":[1,2,3,4,5,6]}}","payloadType":"json","x":950,"y":2580,"wires":[["c0039a0b6001719d"]]},{"id":"b02d1f27bc877009","type":"inject","z":"d1395164b4eec73e","name":"no dps","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{}}","payloadType":"json","x":950,"y":2640,"wires":[["c0039a0b6001719d"]]}]

With nullish chaining no error is thrown.

Well I guess you are swapping 1 possible error for a possible set of other errors - as always, multiple ways to do things, each with strengths and weaknesses.

No not really, just pointing out another way as you say

Could you show examples of other errors so others can see the possibilities?

Some comments here:

Try this article:

Or maybe this:

Could you supply an example flow of the errors you speak of? It would make life easier for others and me to understand your point.

Sorry, focused on other things right now.

Maybe later then?
Never mind as you are to busy, I will add it to show what @GogoVega means, by using Object.create() and it you set a null prototype.

[{"id":"51a806170b1fc6f9","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1000,"y":2520,"wires":[["3a92bd350b6e25b7"]]},{"id":"67945dd7ba95413d","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":980,"y":2340,"wires":[["7132475e275fd915"]]},{"id":"7132475e275fd915","type":"function","z":"d1395164b4eec73e","name":"calling hasOwnProperty as instance with a null prototype, causes error","func":"// the prototype for newly created object.\nmsg.payload = Object.create(null); // Setting `null` as prototype for payload \n\n// Adding a 'name' property on the instance\nmsg.payload.name = 'peter';\n\n// Using `hasOwnProperty` method would cause an error\nmsg.payload.hasOwnProperty('name'); //\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1310,"y":2340,"wires":[["9bff22b548d19bc2"]]},{"id":"9bff22b548d19bc2","type":"debug","z":"d1395164b4eec73e","name":"debug 2461","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1650,"y":2340,"wires":[]},{"id":"4e5c51173f514039","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":980,"y":2420,"wires":[["f0177836c67f7bfa"]]},{"id":"f0177836c67f7bfa","type":"function","z":"d1395164b4eec73e","name":"calling hasOwnProperty as instance with no null prototype","func":"// the prototype for newly created object.\nmsg.payload = Object.create({}); // Setting `null` as prototype for payload \n\n// Adding a 'name' property on the instance\nmsg.payload.name = 'peter';\n\n// Using `hasOwnProperty` method would cause an error\nmsg.payload.hasOwnProperty('name'); //\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1270,"y":2420,"wires":[["8a6fc9bacc7d3ea5"]]},{"id":"8a6fc9bacc7d3ea5","type":"debug","z":"d1395164b4eec73e","name":"debug 2463","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1590,"y":2420,"wires":[]},{"id":"3a92bd350b6e25b7","type":"function","z":"d1395164b4eec73e","name":"calling hasOwnProperty as Object.prototype with null prototype","func":"// the prototype for newly created object.\nmsg.payload = Object.create(null); // Setting `null` as prototype for payload \n\n// Adding a 'name' property on the instance\nmsg.payload.name = 'peter';\n\n// Using `hasOwnProperty` method would cause an error\nObject.prototype.hasOwnProperty.call(msg.payload,'name'); //\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1250,"y":2520,"wires":[["22eaf94ff9b51c88"]]},{"id":"22eaf94ff9b51c88","type":"debug","z":"d1395164b4eec73e","name":"debug 2462","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1530,"y":2520,"wires":[]}]

thanks for the replies

I tried to use if (Object.prototype.hasOwnProperty.call(msg.payload.data.dps, "1")) {

but I keep getting this error: "TypeError: Cannot read properties of undefined (reading '1')"

this is the payload:

image

I just want to know if the element 1 under data-> DPS exists or not, don't care about the value

The error is coming from somewhere else in your code as I see nothing wrong in the if statement with the object you show.

Thanks for the reply. I'm not sure where the error is coming from.

here is the code:

let secondpayload = {};
let thirdpayload = {};

if (Object.prototype.hasOwnProperty.call(msg.payload.data.dps, "1")) {

    
if (msg.payload.dps["1"] === "1") {
    msg.colour = "#1db954";
    secondpayload = { colour: "#ffffff" };
    thirdpayload = { colour: "#ffffff" };
global.set("masterblindup", 1);
global.set("masterblinddown", 0);
global.set("masterblindstop", 0);
    return [msg, secondpayload, thirdpayload];

}

else if (msg.payload.dps["1"] === "2") {
     secondpayload = { colour: "#1db954" };
    msg.colour = "#ffffff";
    thirdpayload = { colour: "#ffffff" };
global.set("masterblinddown", 1);
global.set("masterblindup", 0);
    global.set("masterblindstop", 0); 
    return [msg, secondpayload, thirdpayload];


}

else if (msg.payload.dps["1"] === "3") {
    thirdpayload = { colour: "#1db954" };
    msg.colour = "#ffffff";
    secondpayload = { colour: "#ffffff" };
global.set("masterblindstop", 1);
global.set("masterblindup", 0);
global.set("masterblinddown", 0);
    return [msg, secondpayload, thirdpayload];

}
}

This is the flow, it's just looking for an output of the Tuya node, which typically outputs the screenshot in the last post .

image

Missing data after payload in your if & else ifs (3 places)

1 Like

Thanks - that mistake is caused by looking at the computer screen too long lol

Some thoughts and examples.

You do not need to use hasOwnProperty and you should rethink how you save your globals. If you save masterblind as a object you can then add extra properties without reworking most of your code later, and all values for masterblind blind are in one global var, for ease of viewing etc.
example flow to follow

[{"id":"a5ca6e3cb9934d6f","type":"inject","z":"d1395164b4eec73e","name":"dps 1 = 1","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":{\"1\":\"1\"}}}","payloadType":"json","x":200,"y":2440,"wires":[["7132475e275fd915"]]},{"id":"7132475e275fd915","type":"function","z":"d1395164b4eec73e","name":"has own or has ownproperty","func":"// set default outputs\nlet output = [\n    { colour: \"#ffffff\" },\n    { colour: \"#ffffff\" },\n    { colour: \"#ffffff\" }\n];\n//set masterblind  default, add new propprties here\nlet masterblind = {\n    \"up\": 0,\n    \"down\": 0,\n    \"stop\": 0\n};\n// check dps using nullish coalescing optional chaining\nif (msg.payload?.data?.dps?.[\"1\"] === \"1\") {\n    output[0].colour = \"#1db954\";\n    masterblind.up = 1;\n    global.set(\"masterblind\", masterblind);\n} else if (msg.payload?.data?.dps?.[\"1\"] === \"2\") {\n    output[1].colour = \"#1db954\";\n    masterblind.down = 1;\n    global.set(\"masterblind\", masterblind);\n} else if (msg.payload?.data?.dps?.[\"1\"] === \"3\") {\n    output[2].colour = \"#1db954\";\n    masterblind.stop = 1;\n    global.set(\"masterblind\", masterblind);\n} else {\n// no out put if no dps 1 and dps 1 does not equal 1 or 2 or 3\n    output = null;\n}\n// set new global masterblind\nreturn output;","outputs":3,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":2480,"wires":[["9bff22b548d19bc2"],["9bff22b548d19bc2"],["9bff22b548d19bc2"]]},{"id":"67945dd7ba95413d","type":"inject","z":"d1395164b4eec73e","name":"dps 1 = 2","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":{\"1\":\"2\"}}}","payloadType":"json","x":200,"y":2480,"wires":[["7132475e275fd915"]]},{"id":"1e4513287fbdd28c","type":"inject","z":"d1395164b4eec73e","name":"dps 1 = 3","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":{\"1\":\"3\"}}}","payloadType":"json","x":200,"y":2520,"wires":[["7132475e275fd915"]]},{"id":"1824d9f6656e93c1","type":"inject","z":"d1395164b4eec73e","name":"no dps 1","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"data\":{\"dps\":{\"2\":\"\"}}}","payloadType":"json","x":200,"y":2560,"wires":[["7132475e275fd915"]]},{"id":"9bff22b548d19bc2","type":"debug","z":"d1395164b4eec73e","name":"debug 2461","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"colour","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":2500,"wires":[]}]

[edit] fixed global.set() in wrong place.

1 Like

On top of that sound advice, this approach there is nothing in that function that couldn't/shouldn't be written in regular flow nodes (switch/change nodes)

1 Like