JavaScript check if property defined [duplicate] - javascript

This question already has answers here:
What's the simplest approach to check existence of deeply-nested object property in JavaScript? [duplicate]
(7 answers)
Closed 10 years ago.
What is the recommended way to check if an object property like obj.prop.otherprop.another is defined?
if(obj && obj.prop && obj.prop.otherprop && obj.prop.otherprop.another)
this works well, but enough ugly.

The most efficient way to do it is by checking for obj.prop.otherprop.another in a try{} catch(exception){} block. That would be the fastest if all the remaining exist; else the exception would be handled.
var a = null;
try {
a = obj.prop.otherprop.another;
} catch(e) {
obj = obj || {};
obj.prop = obj.prop || {};
obj.prop.otherprop = obj.prop.otherprop || {};
obj.prop.otherprop.another = {};
a = obj.prop.otherprop.another ;
}

Not saying this is better but ...
x = null
try {
x = obj.prop.otherprop.another;
} catch() {}
// ...
Or alternatively ...
function resolve(obj, path) {
path = path.split('.');
while (path.length && obj) obj = obj[path.shift()];
return obj;
}
x = resolve(obj, 'prop.otherprop.another');
... but I guess the actual answer is that there isn't a best-practice for this. Not that I'm aware of.

If you're in a silly mood, this would work:
if ((((obj || {}).prop || {}).anotherprop || {}).another) { ... }
But I don't know if initializing three new objects is really worth not having to repeatedly type out the path.

Related

javascript - check if object is empty [duplicate]

This question already has answers here:
How do I test for an empty JavaScript object?
(48 answers)
Closed 1 year ago.
I am trying to create to javascript/jquery test to check if my object is empty and cannot figure it out.
Here is the object when it has something in it:
{"mergedSellerArray":{"key1114":"1120"}}
And here is the object when empty:
{"mergedSellerArray":{}}
This is the current test I have based on another SO answer but it does not work:
var sellers = JSON.stringify({mergedSellerArray});
if(Object.keys(sellers).length === 0 && sellers.constructor === Object) {
console.log("sellers is empty!");
}
You were testing sellers which is not empty because it contains mergedSellerArray. You need to test sellers.mergedSellerArray
let sellers = {
"mergedSellerArray": {}
};
if (Object.keys(sellers.mergedSellerArray).length === 0 && sellers.mergedSellerArray.constructor === Object) {
console.log("sellers is empty!");
} else {
console.log("sellers is not empty !");
}
If you are using lodash library, you have an elegant way to check an empty object, array, map or a set.
I presume you are aware of ES6 Import statement.
import {isEmpty} from "lodash"
let obj = {};
console.log(isEmpty(obj)); //Outputs true.
let arr = [];
console.log(isEmpty(arr)); //Outputs true.
obj.name="javascript";
console.log(isEmpty(obj)); //Outputs false.
So, for your code,
isEmpty(mergedSellerArray); //will return true if object is not empty.
Hope this answer helped.
This will work in modern web browser. It is quite easy and simple
const empty = {};
if(Object.keys(empty).length === 0 && empty.constructor === Object) {
console.log("Object is empty");
} else {
console.log("Object is not empty");
}
Here is in jQuery:
$(document).ready(function(){
var obj={"mergedSellerArray":{}};
alert("is empty: "+$.isEmptyObject(obj.mergedSellerArray));
var obj2={"mergedSellerArray":{"key1114":"1120"}};
alert("is empty: "+$.isEmptyObject(obj2.mergedSellerArray));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js" />
jsfidle: https://jsfiddle.net/nyqgbp38/
Can create the helper function :
const isEmpty = inputObject => {
return Object.keys(inputObject).length === 0;
};
Can use it like:
let inputObject = {};
console.log(isEmpty(inputObject)) // true.
and
inputObject = {name: "xyz"};
console.log(isEmpty(inputObject)) // false

Initializing an array in Javascript returns an object [duplicate]

This question already has answers here:
How do I check if a variable is an array in JavaScript?
(24 answers)
Closed 1 year ago.
I'm trying to write a function that either accepts a list of strings, or a single string. If it's a string, then I want to convert it to an array with just the one item so I can loop over it without fear of an error.
So how do I check if the variable is an array?
The method given in the ECMAScript standard to find the class of Object is to use the toString method from Object.prototype.
if(Object.prototype.toString.call(someVar) === '[object Array]') {
alert('Array!');
}
Or you could use typeof to test if it is a string:
if(typeof someVar === 'string') {
someVar = [someVar];
}
Or if you're not concerned about performance, you could just do a concat to a new empty Array.
someVar = [].concat(someVar);
There's also the constructor which you can query directly:
if (somevar.constructor.name == "Array") {
// do something
}
Check out a thorough treatment from T.J. Crowder's blog, as posted in his comment below.
Check out this benchmark to get an idea which method performs better: http://jsben.ch/#/QgYAV
From #Bharath, convert a string to an array using ES6 for the question asked:
const convertStringToArray = (object) => {
return (typeof object === 'string') ? Array(object) : object
}
Suppose:
let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']
In modern browsers you can do:
Array.isArray(obj)
(Supported by Chrome 5, Firefox 4.0, Internet Explorer 9, Opera 10.5 and Safari 5)
For backward compatibility you can add the following:
// Only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
};
If you use jQuery you can use jQuery.isArray(obj) or $.isArray(obj). If you use Underscore.js you can use _.isArray(obj).
If you don't need to detect arrays created in different frames you can also just use instanceof:
obj instanceof Array
I would first check if your implementation supports isArray:
if (Array.isArray)
return Array.isArray(v);
You could also try using the instanceof operator
v instanceof Array
jQuery also offers an $.isArray() method:
var a = ["A", "AA", "AAA"];
if($.isArray(a)) {
alert("a is an array!");
} else {
alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This is the fastest among all methods (all browsers supported):
function isArray(obj){
return !!obj && obj.constructor === Array;
}
Imagine you have this array below:
var arr = [1,2,3,4,5];
JavaScript (new and older browsers):
function isArray(arr) {
return arr.constructor.toString().indexOf("Array") > -1;
}
or
function isArray(arr) {
return arr instanceof Array;
}
or
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
Then call it like this:
isArray(arr);
JavaScript (Internet Explorer 9+, Chrome 5+, Firefox 4+, Safari 5+, and Opera 10.5+)
Array.isArray(arr);
jQuery:
$.isArray(arr);
Angular:
angular.isArray(arr);
Underscore.js and Lodash:
_.isArray(arr);
Array.isArray works fast, but it isn't supported by all versions of browsers.
So you could make an exception for others and use a universal method:
Utils = {};
Utils.isArray = ('isArray' in Array) ?
Array.isArray :
function (value) {
return Object.prototype.toString.call(value) === '[object Array]';
}
A simple function to check this:
function isArray(object)
{
return object.constructor === Array;
}
You can use Array.isArray(). Here is a polyfill:
if (Array.isArray == null) {
Array.isArray = (arr) => Object.prototype.toString.call(arr) === "[object Array]"
}
As MDN says in here:
use Array.isArray or Object.prototype.toString.call to differentiate
regular objects from arrays
Like this:
Object.prototype.toString.call(arr) === '[object Array]', or
Array.isArray(arr)
There's just one line solution for this question
x instanceof Array
where x is the variable it will return true if x is an array and false if it is not.
I would make a function to test the type of object you are dealing with...
function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }
// tests
console.log(
whatAmI(["aiming","#"]),
whatAmI({living:4,breathing:4}),
whatAmI(function(ing){ return ing+" to the global window" }),
whatAmI("going to do with you?")
);
// output: Array Object Function String
then you can write a simple if statement...
if(whatAmI(myVar) === "Array"){
// do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
// do string stuff
}
You can check the type of your variable whether it is an array with;
var myArray=[];
if(myArray instanceof Array)
{
....
}
I do this in a very simple way. It works for me.
Array.prototype.isArray = true;
a=[]; b={};
a.isArray // true
b.isArray // (undefined -> false)
This is my attempt to improve on this answer taking into account the comments:
var isArray = myArray && myArray.constructor === Array;
It gets rid of the if/else, and accounts for the possibility of the array being null or undefined
I have updated the jsperf fiddle with two alternative methods as well as error checking.
It turns out that the method defining a constant value in the 'Object' and 'Array' prototypes is faster than any of the other methods. It is a somewhat surprising result.
/* Initialisation */
Object.prototype.isArray = function() {
return false;
};
Array.prototype.isArray = function() {
return true;
};
Object.prototype._isArray = false;
Array.prototype._isArray = true;
var arr = ["1", "2"];
var noarr = "1";
/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");
These two methods do not work if the variable takes the undefined value, but they do work if you are certain that they have a value. With regards to checking with performance in mind if a value is an array or a single value, the second method looks like a valid fast method. It is slightly faster than 'instanceof' on Chrome, twice as fast as the second best method in Internet Explorer, Opera and Safari (on my machine).
I know, that people are looking for some kind of raw JavaScript approach. But if you want think less about it, take a look at Underscore.js' isArray:
_.isArray(object)
It returns true if object is an Array.
(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
The best practice is to compare it using constructor, something like this
if(some_variable.constructor === Array){
// do something
}
You can use other methods too, like typeOf, converting it to a string and then comparing, but comparing it with dataType is always a better approach.
The best solution I've seen is a cross-browser replacement for typeof. Check Angus Croll's solution.
The TL;DR version is below, but the article is a great discussion of the issue so you should read it if you have time.
Object.toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)
// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};
If the only two kinds of values that could be passed to this function are a string or an array of strings, keep it simple and use a typeof check for the string possibility:
function someFunc(arg) {
var arr = (typeof arg == "string") ? [arg] : arg;
}
Here's my lazy approach:
if (Array.prototype.array_ === undefined) {
Array.prototype.array_ = true;
}
// ...
var test = [],
wat = {};
console.log(test.array_ === true); // true
console.log(wat.array_ === true); // false
I know it's sacrilege to "mess with" the prototype, but it appears to perform significantly better than the recommended toString method.
Note: A pitfall of this approach is that it wont work across iframe boundaries, but for my use case this is not an issue.
This function will turn almost anything into an array:
function arr(x) {
if(x === null || x === undefined) {
return [];
}
if(Array.isArray(x)) {
return x;
}
if(isString(x) || isNumber(x)) {
return [x];
}
if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
return Array.from(x);
}
return [x];
}
function isString(x) {
return Object.prototype.toString.call(x) === "[object String]"
}
function isNumber(x) {
return Object.prototype.toString.call(x) === "[object Number]"
}
It uses some newer browser features so you may want to polyfill this for maximum support.
Examples:
> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]
N.B. strings will be converted into an array with a single element instead of an array of chars. Delete the isString check if you would prefer it the other way around.
I've used Array.isArray here because it's the most robust and also simplest.
The following could be used if you know that your object doesn't have a concat method.
var arr = [];
if (typeof arr.concat === 'function') {
console.log("It's an array");
}
var a = [], b = {};
console.log(a.constructor.name == "Array");
console.log(b.constructor.name == "Object");
There is a nice example in Stoyan Stefanov's book JavaScript Patterns which is supposed to handle all possible problems as well as use the ECMAScript 5 method Array.isArray().
So here it is:
if (typeof Array.isArray === "undefined") {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
};
}
By the way, if you are using jQuery, you can use its method $.isArray().
You could use the isArray method, but I would prefer to check with:
Object.getPrototypeOf(yourvariable) === Array.prototype
function isArray(value) {
if (value) {
if (typeof value === 'object') {
return (Object.prototype.toString.call(value) == '[object Array]')
}
}
return false;
}
var ar = ["ff","tt"]
alert(isArray(ar))
A simple function for testing if an input value is an array is the following:
function isArray(value)
{
return Object.prototype.toString.call(value) === '[object Array]';
}
This works cross browser, and with older browsers. This is pulled from T.J. Crowders' blog post
You can try this:
var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();
arr.constructor.prototype.hasOwnProperty('push') //true
obj.constructor.prototype.hasOwnProperty('push') // false
In your case you may use concat method of Array which can accept single objects as well as array (and even combined):
function myFunc(stringOrArray)
{
var arr = [].concat(stringOrArray);
console.log(arr);
arr.forEach(function(item, i)
{
console.log(i, "=", item);
})
}
myFunc("one string");
myFunc(["one string", "second", "third"]);
concat seems to be one of the oldest methods of Array (even IE 5.5 knows it well).

How to get all possible methods that can be called on a variable in js (including non object varibles like a number)

For debugging purposes, I would like to know (in runtime) all possible methods that I can call on a specific js variable.
This can be done in Chrome console (and others), but I like a javascript method that gives me an array with strings of the names of all methods that can be called on a variable.
If you use "for..in" or Object.keys, we dont get all method!
(If you call these on a variable containing a number, it doesn't include methods defined in Number.prototype!)
Any ideas?
Okay for others who have same problem I ended up writing this method.
var getKeys = function(obj){
var keys = [], k;
if (typeof obj !== "object" && typeof obj !== "function" || obj === null) {
//primitive
}else{
for (k in obj){
if(keys.indexOf(k) === -1){
keys.push(k);
}
}
}
var type = Object.prototype.toString.call(obj).slice(8, -1);
var prototype_keys = Object.getOwnPropertyNames(window[type].prototype);
for (k = 0; k<prototype_keys.length;k++){
if(keys.indexOf(prototype_keys[k]) === -1){
keys.push(prototype_keys[k]);
}
}
return keys;
};

Null Checks for a large hierarchical object in Javascript [duplicate]

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 8 years ago.
We have a large hierarchical object (worst possible legacy design) in javascript. The problem I am facing is that there is a list of null checks I need to perform whenever I want to access an element deep within the object structure.
Say I have a bank object which contains a list of customers and I want to get the address of the first customer,
if(bank != null ||
bank.customerlist != null ||
bank.customerlist.customer[0] != null ||
bank.customerlist.customer[0].address != null )
{
transactionAddress = bank.customerlist.customer[0].address;
}
This is just a small example,I cannot believe so many null checks are required
just to access a single value.
It there a better way around this?
You can use try catch block:
try {
var transactionAddress = bank.customerlist.customer[0].address;
} catch(e) {
// handle the error here
}
You could create your own accesser function:
function access(obj, path) {
var arr = path.split('/');
while(obj && arr.length)
obj = obj[arr.shift()];
return obj;
}
And use it like this:
var bank = {
customerlist: {customer: [{address: 'foo'}]}
}
access(bank, 'customerlist/customer/0/address'); // 'foo'
access(bank, 'bar/foo/foobar'); // undefined (no error)
Also consider using...
function access(obj, path) {
var arr = path.split('/');
while(obj!=null && arr.length)
obj = obj[arr.shift()];
return obj;
}
...if you want to use access with non-objects, e.g. you want access('', 'length') to return 0
Explaining,
function access(obj, path) {
var arr = path.split('/');
while (
obj /* To avoid `null` and `undefined`. Also consider `obj != null` */
&& /* Logical AND */
arr.length /* Check that `arr` still has elements */
) {
obj = obj[arr.shift()]; /* `arr.shift()` extracts the first
element is `arr` */
}
return obj;
}

Updating JavaScript object-attributes from another object [duplicate]

This question already has answers here:
How can I merge properties of two JavaScript objects dynamically?
(69 answers)
Closed 6 years ago.
I want to update an object that could look like this:
currentObject = {
someValue : "value",
myObject : {
attribute1 : "foo",
attribute2 : "bar"
}
};
.. with an object that contains some changes i.e.:
updateObject = {
myObject : {
attribute2 : "hello world"
}
};
At the end I would like to have currentObject updated so that:
currentObject.myObject.attribute2 == "hello world"
That should be posible for other objects as well..
As a solution I thought about iterating over the object and somehow take care of the namespace. But I wonder if there is an easy solution for that problem by using a library like jQuery or prototype.
I suggest using underscore.js (or better, lo-dash) extend:
_.extend(destination, *sources)
Copy all of the properties in the source objects over to the
destination object, and return the destination object. It's in-order,
so the last source will override properties of the same name in
previous arguments.
_.extend({name: 'moe'}, {age: 50});
=> {name: 'moe', age: 50}
function update(obj/*, …*/) {
for (var i=1; i<arguments.length; i++) {
for (var prop in arguments[i]) {
var val = arguments[i][prop];
if (typeof val == "object") // this also applies to arrays or null!
update(obj[prop], val);
else
obj[prop] = val;
}
}
return obj;
}
should do the trick: update(currentObject, updateObject). You might want to add some type checks, like Object(obj) === obj to extend only real objects with real objects, use a correct loop for arrays or hasOwnProperty tests.
Here's an Object.keys and recursive example:
// execute object update function
update(currentObject, updateObject)
// instantiate object update function
function update (targetObject, obj) {
Object.keys(obj).forEach(function (key) {
// delete property if set to undefined or null
if ( undefined === obj[key] || null === obj[key] ) {
delete targetObject[key]
}
// property value is object, so recurse
else if (
'object' === typeof obj[key]
&& !Array.isArray(obj[key])
) {
// target property not object, overwrite with empty object
if (
!('object' === typeof targetObject[key]
&& !Array.isArray(targetObject[key]))
) {
targetObject[key] = {}
}
// recurse
update(targetObject[key], obj[key])
}
// set target property to update property
else {
targetObject[key] = obj[key]
}
})
}
JSFiddle demo (open console).
A simple implementation would look like this.
function copyInto(target /*, source1, sourcen */) {
if (!target || typeof target !== "object")
target = {};
if (arguments.length < 2)
return target;
for (var len = arguments.length - 1; len > 0; len--)
cloneObject(arguments[len-1], arguments[len]);
return target;
}
function cloneObject(target, source) {
if (!source || !target || typeof source !== "object" || typeof target !== "object")
throw new TypeError("Invalid argument");
for (var p in source)
if (source.hasOwnProperty(p))
if (source[p] && typeof source[p] === "object")
if (target[p] && typeof target[p] === "object")
cloneObject(target[p], source[p]);
else
target[p] = source[p];
else
target[p] = source[p];
}
This assumes no inherited properties should be cloned. It also does no checks for things like DOM objects, or boxed primitives.
We need to iterate in reverse through the arguments so that the copy is done in a right to left matter.
Then we make a separate cloneObject function to handle the recursive copying of nested objects in a manner that doesn't interfere with the right to left copying of the original object arguments.
It also ensures that the initial target is a plain object.
The cloneObject function will throw an error if a non-object was passed to it.

Categories