According to the MDN document. the in operator can check whether a specified value is in a specified object.
The in operator returns true if the specified property is in the specified object or its prototype chain
I have the below code:
var array = [1.1,2.1];
var status = 1.1 in array;
console.log(status);
the output is false. However, I expect to get the true instead.
another code:
var array = [1,2];
var status = 1 in array;
console.log(status);
the output is true.
Question
why integer can work well with the in operator and the floating numbers can't?
what is the working mechanism of the in operator?
According to the MDN document. the in operator can check whether a specified value is in a specified object
No. It says property, not value.
There is no array[1.1]. The members of the array have integer property names (0 and 1 for an array of length 2).
e.g.
var array = [1.1, 2.1];
console.log("length" in array, array.length);
console.log(0 in array, array[0]);
console.log("find" in array, array.find);
// And it works perfectly well for floats if there is a matching property to find
var object = { "1.1": "hello, world" };
console.log(1.1 in object, object[1.1]);
Use the includes method to test for the presence of a value in an array.
You can use the find function.
The find() method returns the value of the first element in the provided array that satisfies the provided testing function. Otherwise it returns undefined
const array = [1.1,2.1];
const status = array.find(element => element == 1.1);
console.log(status);
Related
I'm trying to understand why Javascript prints an empty array when it should have at least one value inside it. Please, check this code:
detail = [];
detail.cat1=[];
detail.cat2=[];
detail.cat3=[];
detail.cat4=[];
var newEntry = {"cod":"01","dt":"2021-10-02 09:07:21.205-07:00"};
detail.cat2.push(newEntry);
console.log(detail);
console.log(detail.length);
console.log(detail.cat2);
The results are:
> Array []
> 0
> Array [Object { cod: "01", dt: "2021-10-02 09:07:21.205-07:00" }]
How could it print [] since I have one object inside? And how can the length be zero? I was using any Javascript online editor, and the result is the same.
Since an array is really an object, we can add methods/properties directly to an individual array.
Then if you want to see the keys in an object for instance, Object.keys won't see it, but Reflect.ownKeys() will.
The Reflect version of defineProperty will return success or fail, while Object's returns the object passed.
Remember Reflect.preventExtensions() will (like it says) stop you or others from extending them.
As far as question about length is there, ".length" gives length of values not properties so it still gives 0
Array is an indexed collection of values, means you can put element at particular index and get element from particular index.
In the below example, you can see that if there are already elements in an array then you can get its length using length property.
Remember: The length of an array is (highest integer index at which the element is present in array + 1)
const arr = [1, 2, 3, 4];
console.log(arr); // prints whole array
console.log(arr.length); // prints length of an array
console.log(arr[2]); // Element at index 2
If you set element at particular index let say arr[8] = "something" then its length will be 9
const arr = [];
arr[8] = "something";
console.log(arr.length) // 9
It is true that array's are objects, so you can set/get values to/from array. But if you set property that is not a numbered index then it will not increase its length but It will set the property to that array object as:
const arr = [];
arr["introduction"] = "I'm an array";
arr.property = "This is a property"
console.log(arr.length);
console.log(arr.introduction);
console.log(arr.property);
When displaying an array, the default Array.prototype.toString method is usually called. This actually calls Array.prototype.join with no arguments, so produces a comma separated string of the elements of the array.
The join method only returns properties that have a positive integer name (an array index, indicating an array element), other properties are ignored by join.
Similarly, only elements of the array affect the length property, ordinarly properties (i.e. those that don't have an array index for their name) don't affect length.
What kind of magic is that, when you Object.keys() on an object with one key only, it will be treated as a string when you reference later using square brackets?
See below for example:
let chosenProducts = [
{
toys: 20
}
];
let toys = "toys";
chosenProducts.forEach(product => {
let name = Object.keys(product);
console.log(Array.isArray(name)); // true
console.log(name) // ['toys']
console.log(toys) // "toys" - string
console.log(product[name]); // 20 - array used = wtf?
console.log(product[toys]); // 20 - string used
});
Object.keys returns an array.
All objects have a toString method.
If you use an object in string context, toString is called implicitly.
Square-bracket property accessor notation is, essentially, string context (unless you pass a Symbol)
The default toString method on an array looks something like: function () { return this.join(","); }
const example1 = ["foo", "bar"];
console.log("" + example1);
const example2 = ["baz"];
console.log("" + example2);
Object.keys returns an array of keys. Your name variable is an array with one element ['toys']. When you access product[name] implicit coercion of name array to string happens which results in product["toys"]
In javascript there are two types of coercions implicit and explicit coercion
When you access with Object's properties they will be string, in case of an array they will be indexes (numbers), but array is also an object, when you add any property in array it can be act as object property(string) and will not get counted towards the length of array.
let arr = [1,3];
arr.val = 20;
console.log(arr.length); // 2
In your example you are accessing object's property product[name] here name is an array. What will happen here is implicit coercion of array to string.
Javascript will automatically call toString method on your object which is an array in this case. There is toString method for Array which is linked to their prototype Array.prototype.toString. You can override that if you want to get different result.
In simple terms when you try to access variable in if conditional expression javascript automatically coerce to Boolean value.
let a = 10;
if(a){
console.log("implicit coercion");
}
if(Boolean(a)){
console.log("explicit coercion");
}
To learn more about Javascript grammar and types.
The following is unintuitive behavior in javascript,
function function1 () {};
function function2 () {};
var class_a_functions = {function1:true, function2:true};
var contained = function1 in class_a_functions;//false
var equals = function1.name in class_a_functions;//true
Why does the in containment test fail even though I have inserted the functions, not their names, into the dictionary?
EDIT:
If it isn't obvious, I am aware that function1.name is "function1". This is why I asked why the test fails "even though I have inserted the functions, not their names".
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in
// Arrays
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
0 in trees // returns true
3 in trees // returns true
6 in trees // returns false cause there's no 6th key in trees Array
"bay" in trees // returns false (you must specify the
// index number, not the value at that index)
"length" in trees // returns true (length is an Array property)
That's why it returns false
On the other case, class_a_functions[0] is the reference to the stored function in Array that's why equality returns true cause fn1() === fn1()
Now after your edited question the above seems like nonsense so I'll answer further:
var class_a_functions = {function1:true, function2:true};
Is now and object where function1 and function2 are simple Properties holding true as Value.
var contained = function1 in class_a_functions;//false
The above returns false cause there's no "function1" Function inside the Object reference class_a_functions
var equals = function1.name in class_a_functions;//true
The above... well, let's go back to MDN, says:
Summary:
The in operator returns true if the specified property
is in the specified object.
So you have a property of function1 Now let's see if is present in the Object class_a_functions ... Yes. So TRUE
I'm not sure why most of the answers are so trivial and don't really address the underlying issue motivating the question, which is that getting the memory address/object hash/object id in javascipt is "impossible", and therefore the equality testing by object reference is also "impossible".
How can I get the memory address of a JavaScript variable?
A solution for that containment problem is to monkey-patch an object to contain a unique property/string that can be used as a key.
The in is used to identify the key not the value.
The in operator tests if a property is in an object. function1 is not a property of the array, it's a member.
There should be
'function1' in class_a_functions;//true
This is because
In a dictionary
obj = {key:5}
this is equal to
obj = {"key":5} // so it will be stored as string
If you will see the docs it says prop is A string or numeric expression representing a property name or array index.
jQuery inArray returns -1 if the array contains single element.
var a = Array(1);
console.log($.inArray(1,a));
This returns -1. But if the array contains 2 or more elements it works perfectly.
var a = Array(1,2,3);
console.log($.inArray(1,a));
Returns perfect position.
Contrary to what you seem to think, Array(1) doesn't create an array with element 1 but an array of size 1. That's a specific behavior you get when you pass only one argument and it's an integer.
From the MDN :
If the only argument passed to the Array constructor is an integer
between 0 and 2^32-1 (inclusive), this returns a new JavaScript array
with length set to that number.
You should probably almost never use this Array constructor whose strange behavior leads to many bugs and which is mostly useless. Use this :
var a = [1];
Could someone explain this (strange) behavior? Why is the length in the first example 3 and not 2, and most importantly, why is the length in the second example 0? As long as the keys are numerical, length works. When they are not, length is 0. How can I get the correct length from the second example? Thank you.
a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"};
alert(a.length); // returns 3
b = [];
b["key1"] = {"string1":"string","string2":"string"};
b["key2"] = {"string1":"string","string2":"string"};
alert(b.length); // returns 0
One thing to note is that there is a difference between regular arrays and associative arrays. In regular arrays (real arrays), the index has to be an integer. On the other hand, associative arrays can use strings as an index. You can think of associative arrays as a map if you like. Now, also note, true arrays always start from zero. Thus in your example, you created an array in the following manner:
a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"}
Javascript was able to convert your string indexes into numbers, hence, your code above becomes:
a = [];
a[1] = {"blah"};
a[2] = {"blah"};
But remember what i said earlier: True arrays start from zero. Therefore, the javascript interpreter automatically assigned a[0] to the undefined. Try it out in either firebug or the chrome/safari console, and you will see something like this when you try to print "a". You should get something like "[undefined, Object, Object]. Hence the size 3 not 2 as you expected.
In your second example, i am pretty sure you are trying to simulate the use of an associated array, which essentially is adding properties to an object. Remember associated arrays enable you to use strings as a key. So in other terms, you are adding a property to the object. So in your example:
b["key1"] = {"string1":"string","string2":"string"};
this really means:
b.key1 = {"string1":"string","string2":"string"};
Initializing b =[] simply creates an array, but your assignment doesn't populate the array. It simply gives "b" extra properties.
length returns 1 + the largest integer key in the object.
In a the largest key is 2 so 1+2 is 3.
In b there are no integer keys (the keys there are key1 and key2 which cannot be converted into ints) so Javascript assumes that the largest key is -1, and 1 + -1 yields 0.
This program will help you see that:
a = [];
a["1"] = {};
a["4"] = {};
alert(a.length); // Prints 5
From the ECMAScript standard, ECMA-262, 5th ed.
15.4.5.2 length
The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.
Note the length property of an array only takes into account array indices, which are integers; setting other properties doesn't affect length.
For an array, a["3"] is equivalent to a[3] (this behavior is specified by ยง 15.4.5.1); 3 is an array index rather than a property. Thus setting a["3"] affects the array's length. b["key1"] is equivalent to b.key1. Setting properties don't affect the length of a collection.