I’m checking if a property 'lessons' (not inherited) is not present in obj,
All these give me true
(typeof obj['lessons'] == undefined)
(!(obj.hasOwnProperty('lessons')))
(!(hasOwnProperty.call(obj,'lessons')))
(!(_.has(obj, 'lessons')))
(!Object.prototype.hasOwnProperty.call(obj, 'lessons’))
but the property is present in the object, when i print keys by using (key in obj). I don't want to use it as it's very slow and my object is huge.
I found this on stackoverflow, but I don't understand what it's trying to do or how to use it with node.js.
I'd also like to know how are the mentioned ways of using hasOwnProperty are different.
EDIT
adding code
My code is:
console.log("LS:",JSON.stringify(obj)) ;
if (typeof obj['lessons'] == undefined)
console.log('typeof undefined');
else {console.log('typeof not undefined');}
if (!(obj.hasOwnProperty('lessons')))
console.log('hasOwnProperty: false');
else {console.log('hasOwnProperty not undefined');}
if (!(hasOwnProperty.call(obj,'lessons')))
console.log('hasOwnProperty.call');
else {console.log('hasOwnProperty.call not undefined');}
if (!(_.has(obj, 'lessons')))
console.log('_.hash');
else {console.log('_has not undefined');}
if (!(_.has(obj, 'lessons')))
{obj['lessons'] = {"levels": []};}
else
{console.log("has lesson level ");}
console.log("Lesson ", JSON.stringify(obj.lessons));
And the output I'm getting is:
LS: {"_id":"N9zmznzAWx","time":"1970-01-01T00:33:36.000Z","lessons":{"levels":["abc"]}}
typeof not undefined
hasOwnProperty: false
hasOwnProperty.call
_.hash
Lesson {"levels":[]}
Same case with all others..
SOLUTION
It works when I use JSON.parse(JSON.stringify(obj)) instead of obj.
Your checks aren't working because Mongoose document objects don't use simple object properties to expose their fields.
Instead, you can use the Document#get method to do this (with your obj renamed to doc):
var isMissing = (doc.get('lessons') === undefined);
Or you can create a plain JS object from your document by calling toObject() on it, and then use hasOwnProperty on that:
var obj = doc.toObject();
var isMissing = !obj.hasOwnProperty('lessons');
Here is a function that I wrote as an example to test three ways you have listed in your question:
function check(obj) {
if (!obj.hasOwnProperty("lessons")) {
console.log('nope');
}
if (!_.has(obj, 'lessons')) {
console.log('nope');
}
if (!obj.lessons) {
console.log('nope');
}
}
Here is JSBIN that runs the function on two objects, one with 'lessons' and one without:
Example JsBIN
typeof returns a string
var obj = {};
console.log(typeof (typeof obj.lessons));
https://jsfiddle.net/0ar2ku7v/
So you must compare it as such:
if (typeof obj.lessons === 'undefined')
console.log('nope');
Related
EDIT: this was marked as a duplicate of a deep cloning question but my question (cf. title and last phrase) is about a way to tell if an object references itself, the deep cloning part is only there to provide context
I am trying to implement a function that will let me deep-copy a nested object without overwriting nested fields (I know lodash can solve this but I'd rather not use it of possible).
This is what I have written :
function copyObject(target, source) {
if (typeof target !== "object" || !target) {
throw 'target nust be a non-null javascript object';
}
Object.entries(source).map(([key, value]) => {
if (typeof value === "object"
&& typeof target[key] === "object"
&& target[key] !== null) {
copyObject(target[key], value);
} else {
target[key] = value;
}
})
return target;
}
the problem is this function would enter a infinite loop if its source parameter is an object that references itself like so (because it would always call itself on the c property of source) :
let src = {
a: "a",
b: "b",
}
src.c = src;
is there a way to know if a reference is part of an object ? I think in C this would be possible by looking at the memory addresses but in JS I don't know.
If I understand the question correctly, you should be good to go with the code bellow at the start of the .map func.
if( Object.is(value, source) ) {
return
}
MDN Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
Object.is() determines whether two values are the same value. Two values are the same if one of the following holds...
both the same object (meaning both values reference the same object in memory)
What does Douglas Crockford mean when he wrote the is_array() test saying that it will fail to identify arrays that were constructed in a different window or frame?
var is_array = function (value) {
return value &&
typeof value === 'object' &&
value.constructor === Array;
Why does the following work across windows and frames?
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
For example, if you have an iframe, which has its own window, any Array constructed in there will fail another window's test. That's because of the last condition, which assumes the current window's Array, which is a different object.
var isArray = document.querySelector("iframe").contentWindow.Array === Array;
// false (wrong, it *is* an array)
jsFiddle.
The latter works through knowing that typeof always says an Array is an "object", as well as looking for properties that exist on Arrays.
However, it can be fooled, by constructing an object that looks like an array.
var isArray = is_array(Object.create({length: 0, splice: function() {}}));
// true (wrong, it *isn't* an array)
jsFiddle.
Another method is to invoke Object's toString() method on it, which will return the internal class.
var isArray = ({}).toString.call(value) == "[object Array]";
// true (correct, it's an array)
jsFiddle.
This works in a multi-window environment and can't be tricked (though there is more overhead examining it this way, but never likely to be a bottleneck).
I think alex's solution is better than Crockford's. This answer is to point the flaw in Crockford's solution.
See this:
I purposefully created a faulty object.
function Stupid(){}
Stupid.prototype.length = 0;
Stupid.prototype.splice = function () {}
var stupid = new Stupid();
is_array(stupid);
// true
Obviously, if you see someone setting length to the prototype, you have every right to smash their head to the wall.
But this is valid:
function Mediocre(){
Object.defineProperty(this, 'length', {
get: function () { return 42; },
enumerable: false
});
}
Mediocre.prototype.splice = function () {}
var m = new Mediocre();
is_array(m);
// true
So, you shouldn't try to outsmart the usual/common methods, because you can't guess what the other developers are going to do.
I execute some function and get a return value. This value could be anything (string, array, object, reference, function). I then pass this result along using JSON.stringify.
Now, the functions and references don't do me much good in the scope they're being delivered to, so the whole "to string, eval" method isn't much use. I'm going to store them in a local array and just pass along an ID to reference them by later. But, I do go ahead and send string data, arrays, and objects (in the "associated array" sense of javascript objects) as those all play very nicely with JSON.stringify.
I'm already using try... JSON.stringify() catch to do this with recursive objects (which JSON.stringify errors on.) But that doesn't account for anything else mentioned above.
What is the most efficient way to check if an value contains a function?
And not
typeof foo === "function"
Because the return might be
["foo", "bar", ["foo", "bar"], function(){...something}]
I don't want to pick apart each individual piece's type either, just return on the whole whether there's ANY functions/objects that cannot be safely stringified. I could probably work out how to loop and check each individual value, but if there's a shortcut or more efficient method someone can think of, I'd like to hear it.
Thanks!
Refining welcome and appreciated!
//your favorite object length checking function could go here
$.objectLength = (function(){
//ie<9
if (typeof Object.keys === "undefined" ){
return function(o){
var count = 0, i;
for (i in o) {
if (o.hasOwnProperty(i)) {
count++;
}
}
return count;
};
//everyone else
} else {
return function(o){
return Object.keys(o).length;
}
}
})();
//comparing our two objects
$.checkMatch = function(a, b){
//if they're not the same length, we're done here. (functions exist, etc)
if (typeof a !== typeof b || typeof a === "object" && typeof b === "object" && a && b && $.objectLength(a) !== $.objectLength(b)){
return false;
//if they are the same length, they may contain deeper objects we need to check.
} else {
var key;
for (key in a){
//make sure it's not prototyped key
if (a.hasOwnProperty(key)){
//if it doesn't exist on the other object
if (!b.hasOwnProperty(key)){
return false;
//if this an object as well
} else if (typeof a[key] === "object"){
//check for a match
if (!$.checkMatch(a[key], b[key])){
return false;
}
//then check if they're not equal (simple values)
} else if (a[key] !== b[key]){
return false
}
}
}
return true;
}
};
//...stuff
//catch recursive objects in parameters
var good = true, sendObject = {"ourobject", "values"}, finalSendObject;
//try to stringify, which rejects infinitely recursive objects
try {
finalSendObject = JSON.stringify(sendObject);
} catch(e){
good = false;
}
//if that passes, try matching the original against the parsed JSON string
if (good && sendObject !== JSON.parse(finalSendObject)){
good = $.checkMatch(sendObject, JSON.parse(finalSendObject));
}
This will not work
But I will leave it up for anyone who thinks of trying it. Working solution coming shortly.
30 seconds later, I figure it out myself.
String it, parse it. If anything changed, it wont be equal to itself.
var checkParse = function(obj){
return obj === JSON.parse(JSON.strigify(obj));
}
Let's say I have an object:
var foo = {'bar1': {'baz1':1}};
And I try to access foo['bar2']['baz2']. If I was just trying to access foo['bar2'], JS would return undefined. But because I'm trying to get the next property after the undefined bar2, JS throws TypeError: Cannot read property 'baz2' of undefined.
Is there some automatic accessor for an object that first checks if baz2 exists in foo before trying to call its properties? I know I could use a try/catch block or an if statement, but I was hoping for a function along the lines of C++'s array::at, that would check for me.
You could write your own pretty easily:
function at(obj, property) {
var props = property.split('.');
for(var i = 0; i < props.length; i++) {
if (typeof obj === 'undefined') {
return;
}
obj = obj[props[i]];
}
return obj;
}
var foo = {'bar1': {'baz1':1}};
console.log(at(foo, 'bar1.baz1'));
// => 1
console.log(at(foo, 'bar2.baz2'));
// => undefined
Keep in mind this is ONLY for objects, like the one you have shown, and NOT for arrays (ie [0, 1, 2]) but my favorite is this one:
if ('bar1' in foo)
This is even useful for, say, HTML5 feature detection.
if ('localStorage' in window)
I could give you one for arrays too, but I feel like the more logical thing would be to compare its length to a given index. And...not insert undefined values into arrays. Y'know. =p
You can use the in operator:
if("bar2" in foo) {
//do stuff with foo['bar2']
}
or you can check to see if foo['bar2'] is undefined:
if(typeof foo['bar2'] !== "undefined") {
//do stuff with foo['bar2']
}
Also, what you're working with are objects and not arrays (well, they're associative arrays, but also objects in JavaScript).
foo['bar2'] && foo['bar2']['baz2'] will do the trick as well.
How do I verify the existence of an object in JavaScript?
The following works:
if (!null)
alert("GOT HERE");
But this throws an Error:
if (!maybeObject)
alert("GOT HERE");
The Error:
maybeObject is not defined.
You can safely use the typeof operator on undefined variables.
If it has been assigned any value, including null, typeof will return something other than undefined. typeof always returns a string.
Therefore
if (typeof maybeObject != "undefined") {
alert("GOT THERE");
}
There are a lot of half-truths here, so I thought I make some things clearer.
Actually you can't accurately tell if a variable exists (unless you want to wrap every second line into a try-catch block).
The reason is Javascript has this notorious value of undefined which strikingly doesn't mean that the variable is not defined, or that it doesn't exist undefined !== not defined
var a;
alert(typeof a); // undefined (declared without a value)
alert(typeof b); // undefined (not declared)
So both a variable that exists and another one that doesn't can report you the undefined type.
As for #Kevin's misconception, null == undefined. It is due to type coercion, and it's the main reason why Crockford keeps telling everyone who is unsure of this kind of thing to always use strict equality operator === to test for possibly falsy values. null !== undefined gives you what you might expect. Please also note, that foo != null can be an effective way to check if a variable is neither undefined nor null. Of course you can be explicit, because it may help readability.
If you restrict the question to check if an object exists, typeof o == "object" may be a good idea, except if you don't consider arrays objects, as this will also reported to be the type of object which may leave you a bit confused. Not to mention that typeof null will also give you object which is simply wrong.
The primal area where you really should be careful about typeof, undefined, null, unknown and other misteries are host objects. They can't be trusted. They are free to do almost any dirty thing they want. So be careful with them, check for functionality if you can, because it's the only secure way to use a feature that may not even exist.
You can use:
if (typeof objectName == 'object') {
//do something
}
Two ways:
typeof for local variables
You can test for a local object using typeof:
if (typeof object !== "undefined") {}
window for global variables
You can test for a global object (one defined on the global scope) by inspecting the window object:
if (window.FormData) {}
If that's a global object, you can use if (!window.maybeObject)
You could use "typeof".
if(typeof maybeObject != "undefined")
alert("GOT HERE");
If you care about its existence only ( has it been declared ? ), the approved answer is enough :
if (typeof maybeObject != "undefined") {
alert("GOT THERE");
}
If you care about it having an actual value, you should add:
if (typeof maybeObject != "undefined" && maybeObject != null ) {
alert("GOT THERE");
}
As typeof( null ) == "object"
e.g. bar = { x: 1, y: 2, z: null}
typeof( bar.z ) == "object"
typeof( bar.not_present ) == "undefined"
this way you check that it's neither null or undefined, and since typeof does not error if value does not exist plus && short circuits, you will never get a run-time error.
Personally, I'd suggest adding a helper fn somewhere (and let's not trust typeof() ):
function exists(data){
data !== null && data !== undefined
}
if( exists( maybeObject ) ){
alert("Got here!");
}
I used to just do a if(maybeObject) as the null check in my javascripts.
if(maybeObject){
alert("GOT HERE");
}
So only if maybeObject - is an object, the alert would be shown.
I have an example in my site.
https://sites.google.com/site/javaerrorsandsolutions/home/javascript-dynamic-checkboxes
The thread was opened quite some time ago. I think in the meanwhile the usage of a ternary operator is the simplest option:
maybeObject ? console.log(maybeObject.id) : ""
I've just tested the typeOf examples from above and none worked for me, so instead I've used this:
btnAdd = document.getElementById("elementNotLoadedYet");
if (btnAdd) {
btnAdd.textContent = "Some text here";
} else {
alert("not detected!");
}
Apart from checking the existence of the object/variable you may want to provide a "worst case" output or at least trap it into an alert so it doesn't go unnoticed.
Example of function that checks, provides alternative, and catch errors.
function fillForm(obj) {
try {
var output;
output = (typeof obj !== 'undefined') ? obj : '';
return (output);
}
catch (err) {
// If an error was thrown, sent it as an alert
// to help with debugging any problems
alert(err.toString());
// If the obj doesn't exist or it's empty
// I want to fill the form with ""
return ('');
} // catch End
} // fillForm End
I created this also because the object I was passing to it could be x , x.m , x.m[z] and typeof x.m[z] would fail with an error if x.m did not exist.
I hope it helps. (BTW, I am novice with JS)
for me this worked for a DOM-object:
if(document.getElementsById('IDname').length != 0 ){
alert("object exist");
}
if (n === Object(n)) {
// code
}
if (maybeObject !== undefined)
alert("Got here!");
set Textbox value to one frame to inline frame using div alignmnt tabbed panel.
So first of all, before set the value we need check selected tabbed panels frame available or not using following codes:
Javascript Code :
/////////////////////////////////////////
<script>
function set_TextID()
{
try
{
if(!parent.frames["entry"])
{
alert("Frame object not found");
}
else
{
var setText=document.getElementById("formx").value;
parent.frames["entry"].document.getElementById("form_id").value=setText;
}
if(!parent.frames["education"])
{
alert("Frame object not found");
}
else
{
var setText=document.getElementById("formx").value;
parent.frames["education"].document.getElementById("form_id").value=setText;
}
if(!parent.frames["contact"])
{
alert("Frame object not found");
}
else
{
var setText=document.getElementById("formx").value;
parent.frames["contact"].document.getElementById("form_id").value=setText;
}
}catch(exception){}
}
</script>
zero and null are implicit pointers. If you arn't doing arithmetic, comparing, or printing '0' to screen there is no need to actually type it. Its implicit. As in implied. Typeof is also not required for the same reason. Watch.
if(obj) console.log("exists");
I didn't see request for a not or else there for it is not included as. As much as i love extra content which doesn't fit into the question. Lets keep it simple.
Think it's easiest like this
if(myobject_or_myvar)
alert('it exists');
else
alert("what the hell you'll talking about");
Or, you can all start using my exclusive exists() method instead and be able to do things considered impossible. i.e.:
Things like: exists("blabla"), or even: exists("foreignObject.guessedProperty.guessNext.propertyNeeded") are also possible...