strange ng-model behaviour (ng-model mapped to array element) - javascript

What should be the right behaviuor when you have a ng-model declaration like this one?
data-ng-model="elements[0]"
The way it works, if elements is already defined in the scope as an array, it works as I'd expected assigning the first element of the array.
But if elements is not declared it assigns this value :
elements = {0:'anyvalue'}
(which makes sense if I'd had written data-ng-model="elements['0']")
In this case :
elements[0]='anyvalue';
elements['0']='anyvalue';
and I cannot read the value of the propery using "dot" notation (elements.0 or elements.'0').
So it looks correct, but a bit weird.
Is this behaviour correct, or it should instantiate an array when the scope variable is not defined?

An array is just a special type of object. If you look at an array in a debugger, all of the values are listed as properties with numeric keys, like the one you show. If you don't initialize the object as an array, it would still accesses the object in the same way, which just means you now have an object with numeric keys and none of the helpful functions from the Array prototype.

Related

difference between using setters or methods in javascript

I am reading about getters and setters in javascript. I would like to know if there is a difference between this two ways of coding with and without setters
first way, without setters.
>obj1 = {
arr: [];
}
>obj1.arr.push('first')
>obj1.arr
[ 'first' ]
Second way, with setters.
>obj2 = {
set add(data) {
this.arr.push(data);
},
arr: []
}
>obj2.add = 'first'
>obj2.arr
[ 'first' ]
The setter syntax in your example does not really prevent the client code to still add a value using the direct push call as in the first code block. So the difference is that you just added another way to do the same thing.
To make a fair comparison, you would have to define the same method in both alternatives: once as a normal method and once as a setter method, and then the difference is just the syntax how the argument is passed to the method, either with obj.add('first') or obj.add = 'first'.
In this actual case I would vote against the setter, because it gives the false impression that if you "assign" another value, the first assigned value is overwritten:
obj.add = 'first';
obj.add = 'second';
... but obviously this is not the case: both values exist in the object now.
First, The set Syntax bind an object property to a defined function. In this particular example, there is no difference between two codes, but let's say for example you want to check if the value is negative before adding it to the array, so you can use set to Encapsulate that behavior.
So basically, using setter is only to add additional encapsulated behavior to the functions of the objects.
The way of accessing the array index called bracket notation. it is equal to dot notation, except the bracket notation allows you to set new properties to objects or arrays dynamically.
Hope this help you.
I think difference only about "how it looks like". Using setters it's closest way for understanding for people who came to js from object oriented languages.
The getter/setter property is not the same as "normal" instance property, one is called "named data property", the other is called "named accessor property".
Please let met quote below part of documents from the ECMAScript 5.1.
https://www.ecma-international.org/ecma-262/5.1/#sec-8.10.1
An Object is a collection of properties. Each property is either a
named data property, a named accessor property, or an internal
property:
A named data property associates a name with an ECMAScript language
value and a set of Boolean attributes.
A named accessor property associates a name with one or two accessor
functions, and a set of Boolean attributes. The accessor functions are
used to store or retrieve an ECMAScript language value that is
associated with the property.
An internal property has no name and is not directly accessible via
ECMAScript language operators. Internal properties exist purely for
specification purposes.
There are two kinds of access for named (non-internal) properties: get
and put, corresponding to retrieval and assignment, respectively.
And
If the value of an attribute is not explicitly specified by this
specification for a named property, the default value defined in Table
7 is used.

How do I access the 'str' value in my object?

I am trying to return the value under the key 'str' in an Object but I am having trouble accessing the value.
This is what is returned in the console:
Currently I am using a map function to go over the array and just return the _str value like so:
let idx = currentArray.map(function(x) {
return x._id._str;
});
However it is still returning the value as an object. How can I get just the value of the _str key?
Here is the full array without specifying the id field. This is what is returned if you jsut return 'x' in the map function.
You've clarified that the screenshot is of x._id. So to access _str, you'd use x._id[0]._str: The _str property is in the object referenced by the 0 property (the first entry in the array x._id refers to).
Note that in general, _-prefixed properties are meant not to be accessed by code outside the code responsible for the objects in question. You don't seem to be responsible for them, so accessing those properties is likely to make your code rely on undocumented properties that may change in the next "dot" release of whatever lib you're using. It's just convention, but it's a very common convention.
If you right click on the property, most browser consoles offer the ability to copy property path.
Based on this SO post and the docs, it appears that you can probably use x._id.str.
If I understand correctly, you are receiving the str value but it is an object instead of the string literal. In other words, you are getting _str: "598..." instead of "598....". A possible solution would be to use the mongo javascript function to convert the str value to a string.
In your case, I think something like return x._id.str; may work as _id is a MongoID.ObjectID.
I've also linked the documentation below for reference.
https://docs.mongodb.com/manual/reference/method/ObjectId/
Here's a relevant SO answer as well: Convert ObjectID (Mongodb) to String in JavaScript
I think you should write x[_id]._str because _id is one of the array objects.

What is the Type of a javascript object property?

Javascript objects use a key value system (like a hash, map, or dictionary in other programming languages). The key is referred to as a property and within an object is written like this:
var object = { property01: value01, property02: value02 }
Within objects we can access the value of the property using two access methods.
object.property01
object['property01']
In the example above property01 and property02:
What is the type of the variable holding the property name, and how is it stored in memory?
I'm not sure if I understand your question correctly, but the closest answer I could reference is this:
Objects are sometimes called associative arrays, since each property is associated with a string value that can be used to access it.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects
It's a variable, but instead of being attached to the window object, it's attached to another variable.

Scopes javascript - different when string and array/object

Was reading this
https://github.com/angular/angular.js/wiki/Understanding-Scopes
and there is same thing on stack overflow:
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
Here is the thing which I do not understand:
Suppose we then do this:
childScope.aString = 'child string'
The prototype chain is not consulted, and a new aString property is added to the childScope. This new property hides/shadows the parentScope property with the same name.
Suppose we then do this:
childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'
The prototype chain is consulted because the objects (anArray and anObject) are not found in the childScope.
So in the object array example - parent scope is updated because the objects (anArray and anObject) are not found in the childScope
But in the first example its the same. Except that it is the string. It is not found in the child scope, so should be updated in parent scope. Why it is not updated in parent scope?
Or why array and object in 2nd example are not created in child scope?
Hope its ok to create new thread based on original thread, because just for comment it is long text and would not be easy to read.
In a sense, all three of those examples are really the same. In the second two examples, there's simply an extra object-to-object "hop". The first one:
childScope.aString = "child string";
There's just one object involved: the "childScope" object. (By the way, the word "scope" here makes me uneasy, but let's move on.)
The second pair of examples involve two objects:
childScope.anArray[1] = "22";
childScope.anObject.property1 = 'child prop1';
The two objects in the first of those two statements is the "childScope" object, and then the "anArray" property of the "childScope" object. Presumably, if the statement doesn't cause an error then the value of that property is an array. I stress value because that's the key difference between this reference to a property of "childScope" and the first example ("aString") - here, we want the value of the property because it must be used for the subsequent reference. In the first "aString" example, the statement was setting the value, so there was no interrogation of the current value.
Once the value of childScope.anArray has been fetched, then that object reference is in turn used in a property reference expression. Here, as in the first "aString" example, we're setting the value of the "1" property of the "anArray" object. That's pretty much exactly the same operation as in the "aString" example. (The "anObject" example is much the same.)
When setting a property value (or an array element value; that's really the same thing), JavaScript does not look for a property up the prototype chain. When using the value of a property, it does. An interesting effect of that is this. In the first "aString" example, if there were an "aString" property on the prototype, then once that property is set on the instance ("childScope"), then the prototype property is effectively hidden from view as far as that instance object is concerned.

Why this simple javascript code does not work

I have the following code:
function show(){
var a=document.getElementById('somediv').style.display;
a="block";
}
The above code does not work, it works if we use
{
var a=document.getElementById('somediv');
a.style.display="block";
}
What is wrong with the above code?
To understand this, you will need to understand a bit about javascript assignments.
There are two types of assignment in javascript when you use the = operator: assignment by value and assignment by reference. While some languages give you a choice of which type of assignment you use at any given time, javascript does not give you a choice. It has a strict set of rules for when it uses each.
An "assignment by value" means that a specific value like the number 3 or the string "none" is assigned into another variable.
An "assignment by reference" means that a pointer to the other variable is placed into your new variable and any edit of the contents of that object will be reflected in both places.
For simple types like strings and numbers and booleans, javascript ALWAYS uses assignment by value. For types like arrays and objects, javascript always does an assignment by reference. That means when you do:
var a=document.getElementById('somediv').style.display;
since the value in the display property is a string, javascript will use assignment by value and the value of the string in the display property is copied to the a variable. Once this copy has been made, the a variable has no connection whatsoever with the display property. You can change the display property and a completely independently as they each have their own copy of the string.
So, when you then do:
a="block";
you are just assigning a new string to the a variable as it has nothing to do with the previous display property.
On the other hand, when you did this:
var a=document.getElementById('somediv');
you were assigning an object to a. And, javascript always assigns objects by reference. That means that a has a pointer to the somediv object. There is no copy, they both point to the exact same object. So, any change you make to either reference will actually be changing the same object. So, when you do:
a.style.display="block";
you are changing the actual DOM object.
The rule I remember is that simple types like numbers, strings and booleans are copied when assigned (assignment by value). Complex types like arrays and objects are not copied and only a pointer to the original object is put in the new variable (assigned by reference) so both point to the exact same object.
Assignment by value is pretty simple. Assignment by reference can be both powerful and occasionally confusing enough to cause bugs in software that doesn't anticipate the consequences of a true reference to the original. Because of this, if you ever want an actual copy of an object, you have to explicitly make a copy of the object because an assignment does not do that for you. On the other hand, it can be very useful to have references to complex objects that you can pass around as long as you understand how it works. There is, in javascript, no way to get a reference to a simple type like a number, string or boolean. It can be put into an object (as a property) and you can then pass a reference to the object, but you can't pass a reference to the simple type.
Here are a few examples:
// define person
var person = {height: 66, hair: "blonde"};
// assign the person object to bob
// because person is an object, the assignment is by reference
var bob = person;
// change bob's hair
bob.hair = "red";
// because assignment was by reference, person and bob are the same
// object so changing one changes the one original
alert(person.hair); // red
// define person
var person = {height: 66, hair: "blonde"};
// assign the person's height to a variable
// because height is a number, the assignment is by value (e.g. it's copied)
var myHeight = person.height;
// change both heights
myHeight = 72;
person.height = 60;
// because assignment was by value, myHeight and person.height are
// completely separate copies so changing one does not affect the other
alert(myHeight); // 72
alert(person.height); // 60
The = is an assignment operator. You are placing something inside a variable. In the first case you set a to be the value of display. Which is a string equal to block or none etc.
In the second case you set a to be the object somediv. You then set the display property on it.
The first case doesn't work because your code say: Set the display property of a string. A string has no display property so it fails. It's like saying:
'foobar'.style.display = 'none'
You have write wrong spell of function.
As per your code document.getElementById('somediv').style.display return current display status of div, So its give error for set display block.
You will directly set div display property like this
function show(){
var a=document.getElementById('somediv').style.display="block";
}

Categories