JS: weird object comparison behavior - javascript

Given this code:
const name = { name: 'amy' };
function greet(person) {
if (person == { name: 'amy' }) {
return 'hey amy';
} else {
return 'hey there';
}
}
console.log(
greet(name) // 'hey amy'
);
console.log(
greet({ name:'amy' }) // 'hey there'
);
console.log(name == { name: 'amy' }); // true
console.log(name === { name: 'amy' }); // false
console.log(Object.is(name, { name: 'amy' })); // false
Why does double-equals comparison return true when using the name variable, but not an object literal?
First, I thought that maybe it's because the objects have the same memory address, but as one can see it's not true.
Moreover, if we turn things upside-down and define the variable inside the function, the comparison returns false! (It is not shown in the code but you can check it out)
I'm seriously confused and will appreciate the explanation.
EDIT:
Here is where I have tested the code. Nodejs and browser console in Chrome give me the regular results, how it should be. So maybe it is something about the interpreter.

The problem here is the use of the word name for your variable.
In a browser, the window object has a name property that must always be a string. If you try to assign something to it that is not a string, it will be converted to one.
Then, when you compare an object with a string, the object will also be converted and the two strings compared. This is why you see it sometimes return true. Example:
// This will end up being assigned to window.name, and will be converted to a string.
var name = {name: "amy"}
console.log(name) // [object Object]
// Then, when you compare that to another object using ==, the object will also be converted to string.
console.log(name == {name: "amy"}) // true, because the string [object Object] is equal to itself.
Change the name of the variable to anything else, or use let or const, and the problem should disappear:
// This will end up being assigned to window.other, but isn't converted to string
var other = {name: "amy"}
console.log(other) // {"name": "amy"}
// Now, both are objects, and unless they are the exact same object, comparing two objects is always false.
console.log(other == {name: "amy"}) // false, no two distinct objects are ever equal
// Using let will not assign this variable to window.
let name = {name: "amy"}
console.log(name) // {"name": "amy"}
// Again, now we compare two distict objects, which always results in false.
console.log(name == {name: "amy"}) // false

You assume that Javascript will perform the comparision with == as you are thinking of it in your mind, but it is not. But as this is a custom object you can't expect Javascript to hand you a custom implementation out of the box. You should implement it yourself.
The only case where this would work is when you use the === operator to check whether the object are the same but by their memory address, thus skipping any custom-object-data-based comparison whatsoever.

Related

How can I check if there is variable in json object [duplicate]

How do I check if a particular key exists in a JavaScript object or array?
If a key doesn't exist, and I try to access it, will it return false? Or throw an error?
Checking for undefined-ness is not an accurate way of testing whether a key exists. What if the key exists but the value is actually undefined?
var obj = { key: undefined };
console.log(obj["key"] !== undefined); // false, but the key exists!
You should instead use the in operator:
var obj = { key: undefined };
console.log("key" in obj); // true, regardless of the actual value
If you want to check if a key doesn't exist, remember to use parenthesis:
var obj = { not_key: undefined };
console.log(!("key" in obj)); // true if "key" doesn't exist in object
console.log(!"key" in obj); // Do not do this! It is equivalent to "false in obj"
Or, if you want to particularly test for properties of the object instance (and not inherited properties), use hasOwnProperty:
var obj = { key: undefined };
console.log(obj.hasOwnProperty("key")); // true
For performance comparison between the methods that are in, hasOwnProperty and key is undefined, see this benchmark:
Quick Answer
How do I check if a particular key exists in a JavaScript object or array?
If a key doesn't exist and I try to access it, will it return false? Or throw an error?
Accessing directly a missing property using (associative) array style or object style will return an undefined constant.
The slow and reliable in operator and hasOwnProperty method
As people have already mentioned here, you could have an object with a property associated with an "undefined" constant.
var bizzareObj = {valid_key: undefined};
In that case, you will have to use hasOwnProperty or in operator to know if the key is really there. But, but at what price?
so, I tell you...
in operator and hasOwnProperty are "methods" that use the Property Descriptor mechanism in Javascript (similar to Java reflection in the Java language).
http://www.ecma-international.org/ecma-262/5.1/#sec-8.10
The Property Descriptor type is used to explain the manipulation and reification of named property attributes. Values of the Property Descriptor type are records composed of named fields where each field’s name is an attribute name and its value is a corresponding attribute value as specified in 8.6.1. In addition, any field may be present or absent.
On the other hand, calling an object method or key will use Javascript [[Get]] mechanism. That is a far way faster!
Benchmark
https://jsben.ch/HaHQt
.
Using in operator
var result = "Impression" in array;
The result was
12,931,832 ±0.21% ops/sec 92% slower
Using hasOwnProperty
var result = array.hasOwnProperty("Impression")
The result was
16,021,758 ±0.45% ops/sec 91% slower
Accessing elements directly (brackets style)
var result = array["Impression"] === undefined
The result was
168,270,439 ±0.13 ops/sec 0.02% slower
Accessing elements directly (object style)
var result = array.Impression === undefined;
The result was
168,303,172 ±0.20% fastest
EDIT: What is the reason to assign to a property the undefined value?
That question puzzles me. In Javascript, there are at least two references for absent objects to avoid problems like this: null and undefined.
null is the primitive value that represents the intentional absence of any object value, or in short terms, the confirmed lack of value. On the other hand, undefined is an unknown value (not defined). If there is a property that will be used later with a proper value consider use null reference instead of undefined because in the initial moment the property is confirmed to lack value.
Compare:
var a = {1: null};
console.log(a[1] === undefined); // output: false. I know the value at position 1 of a[] is absent and this was by design, i.e.: the value is defined.
console.log(a[0] === undefined); // output: true. I cannot say anything about a[0] value. In this case, the key 0 was not in a[].
Advice
Avoid objects with undefined values. Check directly whenever possible and use null to initialize property values. Otherwise, use the slow in operator or hasOwnProperty() method.
EDIT: 12/04/2018 - NOT RELEVANT ANYMORE
As people have commented, modern versions of the Javascript engines (with firefox exception) have changed the approach for access properties. The current implementation is slower than the previous one for this particular case but the difference between access key and object is neglectable.
It will return undefined.
var aa = {hello: "world"};
alert( aa["hello"] ); // popup box with "world"
alert( aa["goodbye"] ); // popup box with "undefined"
undefined is a special constant value. So you can say, e.g.
// note the three equal signs so that null won't be equal to undefined
if( aa["goodbye"] === undefined ) {
// do something
}
This is probably the best way to check for missing keys. However, as is pointed out in a comment below, it's theoretically possible that you'd want to have the actual value be undefined. I've never needed to do this and can't think of a reason offhand why I'd ever want to, but just for the sake of completeness, you can use the in operator
// this works even if you have {"goodbye": undefined}
if( "goodbye" in aa ) {
// do something
}
"key" in obj
Is likely testing only object attribute values that are very different from array keys
Checking for properties of the object including inherited properties
Could be determined using the in operator which returns true if the specified property is in the specified object or its prototype chain, false otherwise
const person = { name: 'dan' };
console.log('name' in person); // true
console.log('age' in person); // false
Checking for properties of the object instance (not including inherited properties)
*2021 - Using the new method ***Object.hasOwn() as a replacement for Object.hasOwnProperty()
Object.hasOwn() is intended as a replacement for Object.hasOwnProperty() and is a new method available to use (yet still not fully supported by all browsers like safari yet but soon will be)
Object.hasOwn() is a static method which returns true if the specified object has the specified property as its own property. If the property is inherited, or does not exist, the method returns false.
const person = { name: 'dan' };
console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false
const person2 = Object.create({gender: 'male'});
console.log(Object.hasOwn(person2, 'gender'));// false
What is the motivation to use it over Object.prototype.hasOwnProperty? - It is recommended to this method use over the Object.hasOwnProperty() because it also works for objects created by using Object.create(null) and for objects that have overridden the inherited hasOwnProperty() method. Although it's possible to solve these kind of problems by calling Object.prototype.hasOwnProperty() on an external object, Object.hasOwn() overcome these problems, hence is preferred (see examples below)
let person = {
hasOwnProperty: function() {
return false;
},
age: 35
};
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object
}
let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - works regardless of how the object was created
}
More about Object.hasOwn can be found here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
Browser compatibility for Object.hasOwn - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility
The accepted answer refers to Object. Beware using the in operator on Array to find data instead of keys:
("true" in ["true", "false"])
// -> false (Because the keys of the above Array are actually 0 and 1)
To test existing elements in an Array: Best way to find if an item is in a JavaScript array?
Three ways to check if a property is present in a javascript object:
!!obj.theProperty
Will convert value to bool. returns true for all but the false value
'theProperty' in obj
Will return true if the property exists, no matter its value (even empty)
obj.hasOwnProperty('theProperty')
Does not check the prototype chain. (since all objects have the toString method, 1 and 2 will return true on it, while 3 can return false on it.)
Reference:
http://book.mixu.net/node/ch5.html
If you are using underscore.js library then object/array operations become simple.
In your case _.has method can be used. Example:
yourArray = {age: "10"}
_.has(yourArray, "age")
returns true
But,
_.has(yourArray, "invalidKey")
returns false
Answer:
if ("key" in myObj)
{
console.log("key exists!");
}
else
{
console.log("key doesn't exist!");
}
Explanation:
The in operator will check if the key exists in the object. If you checked if the value was undefined: if (myObj["key"] === 'undefined'), you could run into problems because a key could possibly exist in your object with the undefined value.
For that reason, it is much better practice to first use the in operator and then compare the value that is inside the key once you already know it exists.
Here's a helper function I find quite useful
This keyExists(key, search) can be used to easily lookup a key within objects or arrays!
Just pass it the key you want to find, and search obj (the object or array) you want to find it in.
function keyExists(key, search) {
if (!search || (search.constructor !== Array && search.constructor !== Object)) {
return false;
}
for (var i = 0; i < search.length; i++) {
if (search[i] === key) {
return true;
}
}
return key in search;
}
// How to use it:
// Searching for keys in Arrays
console.log(keyExists('apple', ['apple', 'banana', 'orange'])); // true
console.log(keyExists('fruit', ['apple', 'banana', 'orange'])); // false
// Searching for keys in Objects
console.log(keyExists('age', {'name': 'Bill', 'age': 29 })); // true
console.log(keyExists('title', {'name': 'Jason', 'age': 29 })); // false
It's been pretty reliable and works well cross-browser.
vanila js
yourObjName.hasOwnProperty(key) : true ? false;
If you want to check if the object has at least one property in es2015
Object.keys(yourObjName).length : true ? false
ES6 solution
using Array#some and Object.keys. It will return true if given key exists in the object or false if it doesn't.
var obj = {foo: 'one', bar: 'two'};
function isKeyInObject(obj, key) {
var res = Object.keys(obj).some(v => v == key);
console.log(res);
}
isKeyInObject(obj, 'foo');
isKeyInObject(obj, 'something');
One-line example.
console.log(Object.keys({foo: 'one', bar: 'two'}).some(v => v == 'foo'));
Optional chaining operator:
const invoice = {customer: {address: {city: "foo"}}}
console.log( invoice?.customer?.address?.city )
console.log( invoice?.customer?.address?.street )
console.log( invoice?.xyz?.address?.city )
See supported browsers list
For those which have lodash included in their project:There is a lodash _.get method which tries to get "deep" keys:
Gets the value at path of object. If the resolved value is undefined,
the defaultValue is returned in its place.
var object = { 'a': [{ 'b': { 'c': 3 } }] };
console.log(
_.get(object, 'a[0].b.c'), // => 3
_.get(object, ['a', '0', 'b', 'c']), // => 3
_.get(object, 'a.b.c'), // => undefined
_.get(object, 'a.b.c', 'default') // => 'default'
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
This will effectively check if that key, however deep, is defined and will not throw an error which might harm the flow of your program if that key is not defined.
To find if a key exists in an object, use
Object.keys(obj).includes(key)
The ES7 includes method checks if an Array includes an item or not, & is a simpler alternative to indexOf.
The easiest way to check is
"key" in object
for example:
var obj = {
a: 1,
b: 2,
}
"a" in obj // true
"c" in obj // false
Return value as true implies that key exists in the object.
Optional Chaining (?.) operator can also be used for this
Source: MDN/Operators/Optional_chaining
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
}
console.log(adventurer.dog?.name) // undefined
console.log(adventurer.cat?.name) // Dinah
An alternate approach using "Reflect"
As per MDN
Reflect is a built-in object that provides methods for interceptable
JavaScript operations.
The static Reflect.has() method works like the in operator as a
function.
var obj = {
a: undefined,
b: 1,
c: "hello world"
}
console.log(Reflect.has(obj, 'a'))
console.log(Reflect.has(obj, 'b'))
console.log(Reflect.has(obj, 'c'))
console.log(Reflect.has(obj, 'd'))
Should I use it ?
It depends.
Reflect.has() is slower than the other methods mentioned on the accepted answer (as per my benchmark test). But, if you are using it only a few times in your code, I don't see much issues with this approach.
We can use - hasOwnProperty.call(obj, key);
The underscore.js way -
if(_.has(this.options, 'login')){
//key 'login' exists in this.options
}
_.has = function(obj, key) {
return hasOwnProperty.call(obj, key);
};
If you want to check for any key at any depth on an object and account for falsey values consider this line for a utility function:
var keyExistsOn = (o, k) => k.split(".").reduce((a, c) => a.hasOwnProperty(c) ? a[c] || 1 : false, Object.assign({}, o)) === false ? false : true;
Results
var obj = {
test: "",
locals: {
test: "",
test2: false,
test3: NaN,
test4: 0,
test5: undefined,
auth: {
user: "hw"
}
}
}
keyExistsOn(obj, "")
> false
keyExistsOn(obj, "locals.test")
> true
keyExistsOn(obj, "locals.test2")
> true
keyExistsOn(obj, "locals.test3")
> true
keyExistsOn(obj, "locals.test4")
> true
keyExistsOn(obj, "locals.test5")
> true
keyExistsOn(obj, "sdsdf")
false
keyExistsOn(obj, "sdsdf.rtsd")
false
keyExistsOn(obj, "sdsdf.234d")
false
keyExistsOn(obj, "2134.sdsdf.234d")
false
keyExistsOn(obj, "locals")
true
keyExistsOn(obj, "locals.")
false
keyExistsOn(obj, "locals.auth")
true
keyExistsOn(obj, "locals.autht")
false
keyExistsOn(obj, "locals.auth.")
false
keyExistsOn(obj, "locals.auth.user")
true
keyExistsOn(obj, "locals.auth.userr")
false
keyExistsOn(obj, "locals.auth.user.")
false
keyExistsOn(obj, "locals.auth.user")
true
Also see this NPM package: https://www.npmjs.com/package/has-deep-value
While this doesn't necessarily check if a key exists, it does check for the truthiness of a value. Which undefined and null fall under.
Boolean(obj.foo)
This solution works best for me because I use typescript, and using strings like so 'foo' in obj or obj.hasOwnProperty('foo')
to check whether a key exists or not does not provide me with intellisense.
const object1 = {
a: 'something',
b: 'something',
c: 'something'
};
const key = 's';
// Object.keys(object1) will return array of the object keys ['a', 'b', 'c']
Object.keys(object1).indexOf(key) === -1 ? 'the key is not there' : 'yep the key is exist';
In 'array' world we can look on indexes as some kind of keys. What is surprising the in operator (which is good choice for object) also works with arrays. The returned value for non-existed key is undefined
let arr = ["a","b","c"]; // we have indexes: 0,1,2
delete arr[1]; // set 'empty' at index 1
arr.pop(); // remove last item
console.log(0 in arr, arr[0]);
console.log(1 in arr, arr[1]);
console.log(2 in arr, arr[2]);
Worth noting that since the introduction of ES11 you can use the nullish coalescing operator, which simplifies things a lot:
const obj = {foo: 'one', bar: 'two'};
const result = obj.foo ?? "Not found";
The code above will return "Not found" for any "falsy" values in foo. Otherwise it will return obj.foo.
See Combining with the nullish coalescing operator
JS Double Exclamation !! sign may help in this case.
const cars = {
petrol:{
price: 5000
},
gas:{
price:8000
}
}
Suppose we have the object above and If you try to log car with petrol price.
=> console.log(cars.petrol.price);
=> 5000
You'll definitely get 5000 out of it. But what if you try to get an
electric car which does not exist then you'll get undefine
=> console.log(cars.electric);
=> undefine
But using !! which is its short way to cast a variable to be a
Boolean (true or false) value.
=> console.log(!!cars.electric);
=> false
In my case, I wanted to check an NLP metadata returned by LUIS which is an object. I wanted to check if a key which is a string "FinancialRiskIntent" exists as a key inside that metadata object.
I tried to target the nested object I needed to check -> data.meta.prediction.intents (for my own purposes only, yours could be any object)
I used below code to check if the key exists:
const hasKey = 'FinancialRiskIntent' in data.meta.prediction.intents;
if(hasKey) {
console.log('The key exists.');
}
else {
console.log('The key does not exist.');
}
This is checking for a specific key which I was initially looking for.
Hope this bit helps someone.
yourArray.indexOf(yourArrayKeyName) > -1
fruit = ['apple', 'grapes', 'banana']
fruit.indexOf('apple') > -1
true
fruit = ['apple', 'grapes', 'banana']
fruit.indexOf('apple1') > -1
false
for strict object keys checking:
const object1 = {};
object1.stackoverflow = 51;
console.log(object1.hasOwnProperty('stackoverflow'));
output: true
These example can demonstrate the differences between defferent ways. Hope it will help you to pick the right one for your needs:
// Lets create object `a` using create function `A`
function A(){};
A.prototype.onProtDef=2;
A.prototype.onProtUndef=undefined;
var a=new A();
a.ownProp = 3;
a.ownPropUndef = undefined;
// Let's try different methods:
a.onProtDef; // 2
a.onProtUndef; // undefined
a.ownProp; // 3
a.ownPropUndef; // undefined
a.whatEver; // undefined
a.valueOf; // ƒ valueOf() { [native code] }
a.hasOwnProperty('onProtDef'); // false
a.hasOwnProperty('onProtUndef'); // false
a.hasOwnProperty('ownProp'); // true
a.hasOwnProperty('ownPropUndef'); // true
a.hasOwnProperty('whatEver'); // false
a.hasOwnProperty('valueOf'); // false
'onProtDef' in a; // true
'onProtUndef' in a; // true
'ownProp' in a; // true
'ownPropUndef' in a; // true
'whatEver' in a; // false
'valueOf' in a; // true (on the prototype chain - Object.valueOf)
Object.keys(a); // ["ownProp", "ownPropUndef"]
const rawObject = {};
rawObject.propertyKey = 'somethingValue';
console.log(rawObject.hasOwnProperty('somethingValue'));
// expected output: true
checking particular key present in given object, hasOwnProperty will works here.
If you have ESLint configured in your project follows ESLint rule no-prototype-builtins. The reason why has been described in the following link:
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(object, key));
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));
New awesome solution with JavaScript Destructuring:
let obj = {
"key1": "value1",
"key2": "value2",
"key3": "value3",
};
let {key1, key2, key3, key4} = obj;
// key1 = "value1"
// key2 = "value2"
// key3 = "value3"
// key4 = undefined
// Can easily use `if` here on key4
if(!key4) { console.log("key not present"); } // Key not present
Do check other use of JavaScript Destructuring

Check if object already exists in object

I want to check if an object already exists in a given object by only having the object.
For instance:
const information = {
...
city: {
Streetname: ''
}
}
Now, I get the city object and want to check if it is already in the information object (without knowing the property name). The city could be n deep in the information object.
To get the property name of an object you can use Object.keys(). The first problem solved.
Now we need to iterate through the whole object including nested objects. This is the second problem.
And compare it to a query object. This is the third problem.
I assume that we have an object that only contains "simple" though nested objects with primitive values (I do not consider objects with functions or arrays)
// let's assume we have this object
const information = {
city: {
Streetname: 'streetname1'
},
house: {
color: "blue",
height: 100,
city: {
findMe: { Streetname: '' } // we want to get the path to this property 'findMe'
}
},
findMeToo: {
Streetname: '' // we also want to get the path to this proeprty 'findMeToo'
},
willNotFindMe: {
streetname: '' // case sensetive
}
}
// this is our object we want to use to find the property name with
const queryObject = {
Streetname : ''
}
If you use === to compare Objects you will always compare by reference. In our case, we are interested to compare the values. There is a rather extensive checking involved if you want to do it for more complex objects (read this SO comment for details), we will use a simplistic version:
// Note that this only evaluates to true if EVERYTHING is equal.
// This includes the order of the properties, since we are eventually comparing strings here.
JSON.stringify(obj1) === JSON.stringify(obj2)
Before we start to implement our property pathfinder I will introduce a simple function to check if a given value is an Object or a primitive value.
function isObject(obj) {
return obj === Object(obj); // if you pass a string it will create an object and compare it to a string and thus result to false
}
We use this function to know when to stop diving deeper since we reached a primitive value which does not contain any further objects. We loop through the whole object and dive deeper every time we find a nested object.
function findPropertyPath(obj, currentPropertyPath) {
const keys = isObject(obj) ? Object.keys(obj) : []; // if it is not an Object we want to assign an empty array or Object.keys() will implicitly cast a String to an array object
const previousPath = currentPropertyPath; // set to the parent node
keys.forEach(key => {
const currentObj = obj[key];
currentPropertyPath = `${previousPath}.${key}`;
if (JSON.stringify(currentObj) === JSON.stringify(queryObject)) console.log(currentPropertyPath); // this is what we are looking for
findPropertyPath(currentObj, currentPropertyPath); // since we are using recursion this is not suited for deeply nested objects
})
}
findPropertyPath(information, "information"); // call the function with the root key
This will find all "property paths" that contain an object that is equal to your query object (compared by value) using recursion.
information.house.city.findMe
information.findMeToo
const contains = (item, data) => item === data || Object.getOwnPropertyNames(data).some(prop => contains(item, data[prop]));
const information = {
city: {
Streetname: ''
}
}
console.log(contains(information.city, information));
console.log(contains({}, information));

Meaning of squared brackets after return in JS - fn(){return{}[]}

I've saw this syntax and I'm not sure what it's basically doing.
My current assumption is, that it checks whether the argument is != null AND is in the return.
fn = function(value) {
return {
1: 'Test1',
2: 'Test2'
}[value];
}
fn() results in undefined
fn(1) results in Test1
fn(2) results in Test2
fn(3) results in undefined
I'm not sure about my assumption. Can someone maybe clarify me and tell me what's the name of this syntax construct (does it have a specific name) ?
Edit: I saw it out of this context with random numbers and there for didn't realized that it is basically just accessing it. Thanks!
It doesn't check anything.
You have an object literal.
{
1: 'Test1',
2: 'Test2'
}
From which you extract a value using square bracket notation
(result of evaluating previous expression)[value]
And then you return the result
return (result of evaluating previous expression)
You could rewrite this as:
fn = function(value) {
var data = {
1: 'Test1',
2: 'Test2'
};
var return_value = data[value];
return return_value;
}
This:
{
1: 'Test1',
2: 'Test2'
}
is an object literal, so its value is an object reference.
This:
[value]
is an object property reference expression. That combined with the object reference gets you an object property value, or undefined if the string value passed to the [ ] operator isn't found as a property name in the object.
The code prefixes that stuff with return, making the result of the property lookup be the returned value of the function.
Thus, the function returns the object property value corresponding to the string value of the argument passed in so long as the argument is a property in that object constant, or undefined otherwise.

form.serializeArray() converts each element into string

Trying to form.serializeArray() and passing serialized data to the server.
Problem: This method also converts boolean and integer to string. And on server side on the basis of the
value , I am trying to get the data type because of which it gives me String everytime.
Actual Output:
[Object { name="para1", value="1"}, Object { name="para2", value="2"}, Object { name="para3", value="true"}, Object { name="para4", value="rep1"}]
Required Output:
[Object { name="para1", value=1}, Object { name="para2", value=2}, Object { name="para3", value=true}, Object { name="para4", value="rep1"}]
Please suggest the solution for this.
You could process the value string of each object and create a new array with converted values. For example, the strings true and false would be converted to their respective boolean value and numbers would be converted to integers. Note that my example below is quite simple and doesn't cover all possibilities (floats are also converted to integers).
Edit: As noted by #sanfor in the comments, every string containing an integer is converted to an integer value, although strings like "123" could also be treated as strings. However, given the information in the question that the type of the input is unknown, this method provides the desired results.
JSFiddle (open the console to see the output):
var values = [
{
name: 'para1',
value: '1'
},
{
name: 'para2',
value: 'true'
},
{
name: 'para3',
value: 'this is a string'
}
];
var result = values.map(function(obj) {
var value;
if (obj.value === 'true') {
value = true;
} else if (obj.value === 'false') {
value = false;
} else if (!isNaN(obj.value)) {
value = parseInt(obj.value);
} else {
value = obj.value;
}
return {
name: obj.name,
value: value
};
});
console.log(result);
As #Vohuman already mentioned, the values are strings as intended. To make them something else you would need to either use some other function to achieve it, or handle the output of the serializeArray afterwards.
More likely solution is to teach your back-end to resolve the type based on the field. You usually know what you are expecting on back-end so you also know the type required and based on that you can (try) to cast it to be correct type.

Finding a property in a JSON Object

I'm creating a JSON object like
tags = {"jon":["beef","pork"],"jane":["chicken","lamb"]};
which was generated using php from an array like
$arr = array(
'jon' => array('beef', 'pork'),
'jane' => array('chicken', 'lamb')
);
$tags = json_encode($arr);
And I want to check if something is in one or the other. None of these seem to work, but something like
if('lamb' in tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
writes NO to the console
if('foo' in tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
also writes NO to the console
so looking at
typeof(tags.jane);
it shows it's an "object" but
console.log(tags);
shows the following:
Object
jane: Array[2]
0: "chicken"
1: "lamb"
length: 2
__proto__: Array[0]
jon: Array[2]
0: "beef"
1: "pork"
length: 2
__proto__: Array[0]
__proto__: Object
so i thought maybe tags.jane may actually be an array and tried
if($.inArray('lamb', tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
which writes YES to the console but
if($.inArray('foo', tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
also writes YES to the console.
Am I incorrectly building the JSON Object? Not targeting the value(s) properly? Any advice is greatly appreciated. If this would be easier as an array instead of an object, I have full control to change it. I'm just a bit stumped at how I should treat this.
jQuery.inArray returns -1 when element is not found. That's true value from the POV of Javascript. Try this:
if($.inArray('foo', tags.jane) != -1) {
Your second set of answers are the way you should go. However, $.inArray returns an index, not a boolean. Any non-zero integer is true, which means when foo is not found, it returns -1 which evaluates to true and prints YES.
Similarly, $.inArray('chicken', tags.jane) would return 0 and cast to false, which is also not the answer you want.
Instead, use $.inArray('foo', tags.jane) !== -1 as your condition.
tags.name will give you the array for that person. So $.inArray("chicken",tags.jane) would see if "chicken" is in jane's tags array. If it's not, you'd get -1, otherwise you'd it's position in the array (using your example, this would return zero, the first array element).
You're using the keyword in for the wrong reason.
The statement ( prop 'in' obj ) checks to see if the object(associated array) has a property with the value of prop.
Since you're using the 'in' keyword on an array, then false is going to be returned because tags.jane is an array with indexes and not an associated array with properties.
If you want to know was values are in the array then loop through and compare.
If you want to use the 'in' keyword then convert your array to an object like so.
tags = {};
// old code
tags.jane = ['lamb', 'food'];
console.log(('lamb' in tags.jane) === false )
// new code
tags.jane = {
'lamb':1,
'food':1
}
console.log(('lamb' in tags.jane) === true )
https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
you can not use
if('foo' in tags.jane))
it should be used as
if (1 in tags.jane)
if you want to check 'foo' is in tags.jane, try this
var inIt = (function() {
var inIt = false;
tags.jane.forEach(function(item) {
inIt = inIt || 'foo' == item;
});
return inIt;
})();

Categories