Here is the line which is causing null or not an object error
if(frm.elements["hdn_retain"+indexval].value==""){
....
} else {
....
}
frm.elements["hdn_retain"+indexval] may be a null object. So, it will have error when getting the value. You can check the frm.elements["hdn_retain"+indexval] if it is null first.
if(frm.elements["hdn_retain"+indexval] != null && frm.elements["hdn_retain"+indexval].value=="")
Either frm or frm.elements["hdn_retain"+indexval] isn't a valid object (doesn't exist in the dom) and therefore you can't access it's property.
you could try something like:
if(frm.elements["hdn_retain"+indexval] && frm.elements["hdn_retain"+indexval].value==""){
Following is the result of alert statement:
alert("frm:::"+frm);
alert("frm elements::::"+frm.elements);
alert("frm hdn_retain :: "+frm.elements["hdn_retain"+indexval]);
frm:::[object]
frm elements::::[object]
frm hdn_retain :: undefined
you can use this utility method getProperty i always use to make sure i get a nested namespace back without worrying about whether or not something is defined:
function getProperty(ns, obj) {
var nsArray = ns.split('.'),
i = 0,
nsLen = nsArray.length;
while (nsLen > 0) {
var newNs = nsArray.shift();
if (obj[newNs]) {
obj = obj[newNs];
} else {
return false;
}
nsLen = nsArray.length;
}
return obj;
};
var index = "hdn_retain" + indexval;
// the following `value` will come back as a valid object/value or a false
value = getProperty('elements.' + index + '.value', frm);
if (value) {
// do whatever
} else {
// do not whatever
}
this can be applied not only to this situation but to any other situation you need to make sure a certain namespace is available before usage.
Related
In an API response, I want to check if a variable exists. If it doesn't, I want to assign it a blank value:
if(!data3.fields[i+2].values.value[0]) {
data3.fields[i+2].values.value[0] = "";
} else {
break;
}
Error in the console is:
Uncaught TypeError: Cannot read property 'value' of undefined
This confuses me because I thought that's exactly what my if the statement was checking. Any ideas what's going on here?
The if check won't protect you from trying to use an undefined variable. In your instance the values property is undefined. If you wanted to test for that you would need to first check that specific property
if(data3.fields[i+2].values !== undefined && data3.fields[i+2].values.value[0]){
//do something with data3.fields[i+2].values.value[0]
}
additionally, if you are in a scenario where you don't even know if data3 exists (for example you are checking for the existence of a third party script, or something else in your environment) you would need to use the typeof operator to be safe. E.G.
if(typeof(ga) !== 'undefined'){ //typeof returns a string. This would be testing for google analytics on a page.
It doesnt work like PHP does (which checks the whole 'chain'). In your example, you actually check if .value[0] of values exists, but dont check if values exists. The full version should be:
if( data3 && && data3.fields[i+2] && data3.fields[i+2].values && !data3.fields[i+2].values.value[0]) {}
In your code ata3.fields[i+2].values is undefined, and you're trying to access value[0] of 'undefined'
Or slightly more simplefied, if you wand to test if d has a value, you have to make sure that a, b and c aldo have a value:
if( a && a.b && a.b.c && !a.b.c.d){ /* ... */ }
You can remove checks on the left side of the checks if you are sure those exist. E.g.: If you know that a.b always exist, you can simplefy:
if( a.b.c && !a.b.c.d){ /* ... */ }
If you really want to make sure the complete property chain is not undefined you have to check every single step and the later ones won't be executed if at least && condition is false.
if (data3 && data3.fields && data3.fields[i+2] && data3.fields[i+2].values && data3.fields[i+2].values.value && data3.fields[i + 2].values.value[0]) {
data3.fields[i + 2].values.value[0] = "";
} else {
break;
}
Another way would be to just do it and catch the exception:
try {
data3.fields[i + 2].values.value[0] = "";
} catch (e) {
break;
}
The error is telling you that data3.fields[i+2].values is undefined. You can't check for a property .value on undefined.
You'd need to verify each property/index belongs along the way if you always want that nested path to default to an empty string.
if (data3.fields[i+2] === undefined) {
data.fields[i+2] = {};
}
if (data3.fields[i+2].values === undefined) {
data3.fields[i+2].values = {};
}
if (data3.fields[i+2].values.value === undefined) {
data3.fields[i+2].values.value = [];
}
// and finally your empty string assignment
if (data3.fields[i+2].values.value[0] === undefined) {
data3.fields[i+2].values.value[0] = '';
}
Depending on your requirements, you might be able to get away with assigning a stub as soon as you know data3.fields[i+2] is undefined.
if (data3.fields[i+2] === undefined) {
data3.fields[i+2] = {
values: {
value: ['']
}
};
}
I've written a couple of functions that effectively replicate JSON.stringify(), converting a range of values into stringified versions. When I port my code over to JSBin and run it on some sample values, it functions just fine. But I'm getting this error in a spec runner designed to test this.
My code:
// five lines of comments
var stringify = function(obj) {
if (typeof obj === 'function') { return undefined;} // return undefined for function
if (typeof obj === 'undefined') { return undefined;} // return undefined for undefined
if (typeof obj === 'number') { return obj;} // number unchanged
if (obj === 'null') { return null;} // null unchanged
if (typeof obj === 'boolean') { return obj;} // boolean unchanged
if (typeof obj === 'string') { return '\"' + obj + '\"';} // string gets escaped end-quotes
if (Array.isArray(obj)) {
return obj.map(function (e) { // uses map() to create new array with stringified elements
return stringify(e);
});
} else {
var keys = Object.keys(obj); // convert object's keys into an array
var container = keys.map(function (k) { // uses map() to create an array of key:(stringified)value pairs
return k + ': ' + stringify(obj[k]);
});
return '{' + container.join(', ') + '}'; // returns assembled object with curly brackets
}
};
var stringifyJSON = function(obj) {
if (typeof stringify(obj) != 'undefined') {
return "" + stringify(obj) + "";
}
};
The error message I'm getting from the tester is:
TypeError: Cannot convert undefined or null to object
at Function.keys (native)
at stringify (stringifyJSON.js:18:22)
at stringifyJSON (stringifyJSON.js:27:13)
at stringifyJSONSpec.js:7:20
at Array.forEach (native)
at Context.<anonymous> (stringifyJSONSpec.js:5:26)
at Test.Runnable.run (mocha.js:4039:32)
at Runner.runTest (mocha.js:4404:10)
at mocha.js:4450:12
at next (mocha.js:4330:14)
It seems to fail with:
stringifyJSON(null) for example
Generic answer
This error is caused when you call a function that expects an Object as its argument, but pass undefined or null instead, like for example
Object.keys(null)
Object.assign(window.UndefinedVariable, {})
As that is usually by mistake, the solution is to check your code and fix the null/undefined condition so that the function either gets a proper Object, or does not get called at all.
Object.keys({'key': 'value'})
if (window.UndefinedVariable) {
Object.assign(window.UndefinedVariable, {})
}
Answer specific to the code in question
The line if (obj === 'null') { return null;} // null unchanged will not
evaluate when given null, only if given the string "null". So if you pass the actual null value to your script, it will be parsed in the Object part of the code. And Object.keys(null) throws the TypeError mentioned. To fix it, use if(obj === null) {return null} - without the qoutes around null.
Make sure that object is not empty (null or undefined ).
Error:
let obj
Object.keys(obj)
Solution:
Object.keys(obj || {})
Make sure that destination object is not empty ( null or undefined ).
You can initialize destination object with empty object like below:
var destinationObj = {};
Object.assign(destinationObj, sourceObj);
This is very useful to avoid errors when accessing properties of null or undefined objects.
null to undefined object
const obj = null;
const newObj = obj || undefined;
// newObj = undefined
undefined to empty object
const obj;
const newObj = obj || {};
// newObj = {}
// newObj.prop = undefined, but no error here
null to empty object
const obj = null;
const newObj = obj || {};
// newObj = {}
// newObj.prop = undefined, but no error here
Adding Object && works before putting the object on to map.
objexts && Object.keys(objexts)?.map((objext, idx) =>
In my case, I added Lucid extension to Chrome and didn't notice the problem at that moment. After about a day of working on the problem and turning the program upside down, in a post someone had mentioned Lucid. I remembered what I had done and removed the extension from Chrome and ran the program again. The problem was gone. I am working with React. I thought this might help.
I solved the same problem in a React Native project. I solved it using this.
let data = snapshot.val();
if(data){
let items = Object.values(data);
}
else{
//return null
}
Replace
if (typeof obj === 'undefined') { return undefined;} // return undefined for undefined
if (obj === 'null') { return null;} // null unchanged
with
if (obj === undefined) { return undefined;} // return undefined for undefined
if (obj === null) { return null;} // null unchanged
If you're using Laravel, my problem was in the name of my Route.
Instead:
Route::put('/reason/update', 'REASONController#update');
I wrote:
Route::put('/reason/update', 'RESONController#update');
and when I fixed the controller name, the code worked!
In my case I had an extra pair of parenthesis ()
Instead of
export default connect(
someVariable
)(otherVariable)()
It had to be
export default connect(
someVariable
)(otherVariable)
Below snippet is sufficient to understand how I encountered the same issue but in a different scenario and how I solved it using the guidance in the accepted answer. In my case I was trying to log the keys of object present in the 0th index of the 'defaultViewData' array using Object.keys() method.
defaultViewData = [{"name": "DEFAULT_VIEW_PLP","value": {"MSH25": "LIST"}}]
console.log('DEFAULT_VIEW', Object.keys(this.props.defaultViewData[0]));
The console.log was not getting printed and I was getting the same error as posted in this question. To prevent that error I added below condition
if(this.props.defaultViewData[0]) {
console.log('DEFAULT_VIEW', Object.keys(this.props.defaultViewData[0]));
}
Adding this check ensured that I didn't get this error. I hope this helps for someone.
Note: This is React.js code. (although to understand the problem it doesn't matter).
reactTraverser.js:6 Uncaught TypeError: Cannot convert undefined or null to object at Function.keys () at reactTraverser.js:6
If you are getting this error on typeScript Try using it without Live Server this error will not be displayed
I have the same problem with a element in a webform. So what I did to fix it was validate.
if(Object === 'null')
do something
Feel kind of stupid to ask..
I want to get something like this:
var value = $scope.settings.paper.font.color || 0;
The problem is that some of the middle objects may not exist.
Is there an ultimate way to get value if all "object chain" exists and get some fallback if not?
For example, in line above if all objects exists, we may return value of color, but if only $scope.settings exists, and there's no paper object in it, i will get an error, not 0.
First of all: There is no builtin function for it.
Shortest generic solution
Simply wrap it into a try - catch
try {
// handles defaultVal if d is undefined
yourVar = typeof a.b.c.d === 'undefined' ? defaultVal:a.b.c.d;
} catch (e) {
// handles defaultVal if a,b or c are undefined
yourVar = defaultVal;
}
Alternative solution
You could use the following function to safely traverse an object (gv - for getValue):
var gv = function(scope, chainStr, defaultValue) {
var chain = chainStr.split('.');
for (var i = 0; i < chain.length; i++) {
var newScope = scope[chain[i]];
if (typeof newScope !== 'undefined') {
scope = newScope;
} else {
return defaultValue;
}
};
return newScope;
};
Like this:
var a = {b:{c:{d:3}}};
console.log(gv(window, 'a.b.c.d', -1));
// 3
console.log(gv(window, 'a.b.c.e', -1));
// -1
console.log(gv(a, 'b.c.d', -1));
// 3
console.log(gv(a, 'b.c.e', -1));
// -1
Sure, just check for the existence of $scope and each property in its namespace:
var value = (typeof $scope != 'undefined' && $scope.settings && $scope.settings.paper && $scope.settings.paper.font && $scope.settings.paper.font.color) || 0;
The last part of the statement in parenthesis will return the value of .font
Example: http://jsfiddle.net/silkster/gM8uh/
You can also make use of build in $parse service:
var value = $parse('settings.paper.font.color || 0')($scope);
It will make all necessary checks behind the scene.
Demo: http://plnkr.co/edit/1GLb5PEvxMzPMYc5ZxZn?p=preview
The title looks a little confusing, so let me show an example:
Markup
<div id="MyDiv"></div>
<div id="SecondaryDiv"></div>
JS
// Set the HTML5 data key 'name' to value 'MyName'
$("#MyDiv").data("name", "MyName");
// Return all divs with the data key 'name' matching 'MyName'
// This works without a hitch
$("div").filter(function () {
return $(this).data("name") === "MyName";
});
// This breaks because I try to add '.toLowerCase()' to the end of the .data() function.
// The error returned is:
// TypeError: $(...).data(...) is undefined
$("div").filter(function () {
return $(this).data("name").toLowerCase() === "myname";
});
How can I ignore case when comparing $(...).data(...) values?
As a side note, even if I do this:
// This throw an error saying:
// TypeError: val is undefined
var val = "";
$("div").filter(function() {
val = $(this).data("name");
return val.toLowerCase() === "myname";
});
you can't run .toLowerCase() on undefined, so test if the return value for .data('name') is undefined first:
$("div").filter(function () {
if ($(this).data("name")) {
return $(this).data("name").toLowerCase() === "myname";
} else {
return false;
};
});
http://jsfiddle.net/mblase75/yX4X2/
or more succinctly:
$("div").filter(function () {
return $(this).data("name") && ($(this).data("name").toLowerCase()==="myname");
});
http://jsfiddle.net/mblase75/yX4X2/1/
(However, be aware that $(this).data("name") can potentially return "falsey" values like false or 0, since .data() attempts to convert strings to their appropriate type. See this question.)
always in the process of learning Javascript and modifying a cool autocomplete library, i am now in front of this :
i need to check if something passed in an object literal is a variable/field (that is to be considered as a simple value) or is something that can be called.
(as MY autocomplete depend on many input fields, i need to "value" the right things, just before the Ajax.Request) so that this declaration (see the 'extra' parts...)
myAutoComplete = new Autocomplete('query', {
serviceUrl:'autoComplete.rails',
minChars:3,
maxHeight:400,
width:300,
deferRequestBy:100,
// callback function:
onSelect: function(value, data){
alert('You selected: ' + value + ', ' + data);
}
// the lines below are the extra part that i add to the library
// an optional parameter, that will handle others arguments to pass
// if needed, these must be value-ed just before the Ajax Request...
, extraParametersForAjaxRequest : {
myExtraID : function() { return document.getElementById('myExtraID').value; }
}
see the "1 // here i'm lost..." below, and instead of 1 => i would like to check, if extraParametersForAjaxRequest[x] is callable or not, and call it if so, keeping only its value if not. So that, i get the right value of my other inputs... while keeping a really generic approach and clean modification of this library...
{
var ajaxOptions = {
parameters: { query: this.currentValue , },
onComplete: this.processResponse.bind(this),
method: 'get'
};
if (this.options.hasOwnProperty('extraParametersForAjaxRequest'))
{
for (var x in this.options.extraParametersForAjaxRequest)
{
ajaxOptions.parameters[x] = 1 // here i'm lost...
}
}
new Ajax.Request(this.serviceUrl, ajaxOptions );
You can do a typeof to see if the parameter is a function, and call it if it is.
var value;
for (var x in this.options.extraParametersForAjaxRequest)
{
value = this.options.extraParametersForAjaxRequest[x];
if (typeof(value) == 'function') {
ajaxOptions.parameters[x] = value();
}
else {
ajaxOptions.parameters[x] = value;
}
}
if (typeof this.options.extraParametersForAjaxRequest[x]==='function') {
}
You should also do this:
if (this.options.extraParametersForAjaxRequest.hasOwnProperty(x) {
if (typeof this.options.extraParametersForAjaxRequest[x]==='function') {
}
}
when iterating through properties of objects, otherwise you can end up looking at prototype members too.
Another suggestion is to make this more readable with an alias for the thing you're working with. So the ultimate would be:
var opts = this.options.extraParametersForAjaxRequest;
// don't need to check for existence of property explicitly with hasOwnProperty
// just try to access it, and check to see if the result is
// truthy. if extraParametersForAjaxRequest isn't there, no error will
// result and "opts" will just be undefined
if (opts)
{
for (var x in opts) {
if (opts.hasOwnProperty(x) && typeof opts[x]==='function') {
}
}
}