Understanding for in loop (javascript) - javascript

Im kinda new to JS and I'm trying to understand how for/in loop really works, here's some sample code:
phoneBook = {};
phoneBook.bill = { name : "bill", lastName "hayder" };
phoneBook.steve = { name : "steve", lastName "garcia" };
for ( obj in phoneBook )
{
console.log(obj);
};
When I run this code I get bill and steve as an output, my question is if that's what the iterator holds why I am allowed to do phoneBook[obj] and work with that?? If I type manually phoneBook[bill] I get an error, I can only phoneBook.bill or phoneBook["bill"].
Thanks for helping.

When you write phonebook[something] it means that something should be an expression that returns a string, and it should find the property whose name is that string.
In the case of phonebook[obj], the value of the variable obj will be the string "bill" or "steve", and it will then look up the corresponding property.
If you write phonebook[bill], it tries to use bill as a variable name, and expects it to contain a string that names a property. But there is no variable named bill, so this gets an error.

Javascript objects are simply key-value pairs.
phoneBook = {};
phoneBook.bill = { name : "bill", lastName: "hayder" };
phoneBook.steve = { name : "steve", lastName: "garcia" };
In this example, the phoneBook object has two key-value properties, bill and steve. But the properties themselves are objects, each containing the properties name and lastName.
Key-value pairs can be accessed via two ways: the object way and the dictionary way. Object way means accessing via phoneBook.bill, and dictionary way means accessing via phoneBook['bill']. Notice that using a dictionary way means simply passing the property name to the object.
Now, phoneBook[bill] is invalid because JS thinks that bill is a variable, and tries to find this. That's why you should use phoneBook['bill'] or phoneBook["bill"]. You can use this dictionary form, but I suggest you use the phoneBook.bill method.
I hope I answered your question. :)

some syntax errors fixed
phoneBook = {};
phoneBook.bill = { name: "bill", lastName: "hayder" };
phoneBook.steve = { name: "steve", lastName: "garcia" };
for (obj in phoneBook)
{
console.log(obj);
};
Javascript basics
phoneBook has a property bill
In javascript this property bill can be referenced using
phoneBook.bill
phoneBook['bill']
when you reference phoneBook[bill] you will recieve an error because javascript is looking for a variable that contains the string bill
what you can do is try it this way
var bill = 'bill';
phoneBook[bill]

Related

Angular/Javascript array find method

I have started to learn angular recently. I came across a code as follows.
Consider this.members as an array of objects. There is an object which has the username bob. I am trying to get that particular object using the below code.
const data = this.members.find(x=>x.userName===username);
So there an object inside the array and I have an object stored in my const data, My doubt is that will both (the object in the array and the object in the const data ) have the same memory address. If someone could answer why changing the const data is also getting reflected in the this.members array. It would be a great help. You can also share some resources if I need to go through them to understand them better.
To shortly answer your question, yes. The data object will have a reference to the object inside this.members.
If you want to prevent that, there are multiple ways I'm sure, but one of them is to use Object.assign.
Example:
let data: any = {};
Object.assign(data, this.members.find(u => u.username === 'bob'));
console.log(this.members); // For example: [{username: 'bob'},{username: 'randy'}]
data.username = 'alex';
console.log(this.members); // Still shows [{username: 'bob'},{username: 'randy'}]
console.log(data); // {username: 'alex'}
Notice here that I am using TypeScript since you mentioned you're working with Angular.
When using Object.assign, a copy of the enumerable properties will be made and assigned to your variable without referencing the source.
See MDN Docs for more details.
Another simple way is to use the spread operator.
let data: any = {};
const foundUser = this.members.find(u => u.username === 'bob');
if (foundUser) {
data = {...foundUser};
}
This will create a new object with the properties from the foundUser.
You can easily try it out.
const members = [
{ username: 'bob' },
{ username: 'daniel' },
];
const data = members.find(x=>x.username==='bob');
data.username = 'bobby';
console.log(members);
That prints
[ {
"username": "bobby" }, {
"username": "daniel" } ]
So yes, changing data will change the array.
The answer for this question is that Arrays in javascript are mutable which means they are reference type which means when I encounter the below line
const data = this.members.find(x=>x.userName===username);
const data will have the same memory location as that of bob in the array. As we all know that if we change data at a memory location every variable/object referring to that memory location will also change as they all point to the same memory location. Hence the array gets updated even though I assign a part of the array and make changes to that part alone.
Note: The above was my expected behavior. if you want the opposite behavior like if you need the const data and this.members to be independent you can use
Copy Array
or you can refer to Maher's answer in the same page.

How to limit the usage of "===" operator in javascript for specific object property

For example, the following two javascript object have properties include "name", "age" and "phoneNumber".
const personA = {
name: Andy,
age: "24",
phoneNumber: "28173516374"
}
const personB = {
name: "Amy",
age: 25,
phoneNumber: "+85 28173516374"
}
For the property "phoneNumber", I don't want others use it with operator "===" to compare with other string like personA.phoneNumber === personB.phoneNumber, because for the value of a phoneNumber, it should be the same either with or without a prepended country code. For other developers who don't have this knowledge background, they possibly use === to do the compare between two variable with value of a phone number and it will raise some bugs.
So I need a way to limit the usage of === on specific property. I have came up with several solutions, but they still have more or less disadvantage.
Solution 1: Transform the type of all properties which represents a phone number from string to an class PhoneNumber, this class will handle all the comparation and value formatting. However, I have to use new to create that object and should modify many places. Because this property is used everywhere in my project. After trying several times, I forgave applying this solution.
Solution2: Use a common function to compare two phone number. As I have said before, not all developers and reviewers know that function. Even if I address it in document, still have someone forget that.
Now I am trying to develop an eslint rules to limit the usage of === on specific property. Do you have other idea?
Sorry for my weak English.
If the task is to control who can read the field value and who cannot, then this can be solved in several ways.
If you can change the structure of the Object, then getters and setters are suitable for you.
MDN: Getter MDN: Setter
A simplified example solution would look like this:
{
let admin;
const personA = {
age: "24",
sex: "man",
privateName: "Jhon",
get name() {
return (admin === true ? this.privateName : "***");
},
set name(v) {
return (admin === true ? this.privateName = v : "***")
}
}
admin = false;
personA.name = "Mary"
console.log(personA.name)
admin = true;
console.log(personA.name)
personA.name = "Mary"
console.log(personA.name)
}
Instead of outputting ***, we can return an exception.
If you cannot change the structure, then the same can be done using a proxy.
MDN: Proxy
If you cannot use a proxy, then you can change the behavior of the object's properties using
Object.defineProperty. That is, set the same getters and setters on an already existing object.
MDN: Object.defineProperty

How to store key value pairs in JavaScript

I'm new to JavaScript and I want a Data Structure for my JavaScript code which stores Student data as key value pairs. The key is the student Registration number and the value is the students name.What I'm thinking is to create a JavaScript object as follows and store data as follows
let Student={
001A:"John",
002A:"Mathew"
};
Is this approach is correct? And if it is correct suppose a way to dynamically add key value pairs to that. Thank you
That would be an object literal. You'd want the key to be a string, but other than that you've basically got it. You can dynamically add properties using bracket syntax. I've attached a small snippet to give you an idea of how it works. :)
let Student={
"001A":"John",
"002A":"Mathew"
};
Student["003A"] = 'Jessica';
Object.entries(Student).forEach(entry => console.log(entry) );
The approach is correct. Given
const students={
'001A': 'John',
'002A': 'Mathew',
};
(Note: It's a good idea to keep your key as a string to prevent collisions with reserved keywords)
To read from the structure you can access the given record via
console.log(students['001A']); // => 'John'
To add new records dynamically, you just add a new property and assign it the desired value:
students['007'] = 'Ben';
which results in
console.log(students);
// =>
{
'001A': 'John',
'002A': 'Mathew',
'007': 'Ben',
};
To delete a given record you can do either
delete students['007'];
or
students['007'] = undefined;
The first option is a little "cleaner" as it completely deletes the given key, along with its assigned data.
Keep in mind that the data will be removed once you reload the page.

JavaScript remove string from a value within an object

I have an object:
let Data = {name: 'Flomo', age: 25, address: 'Sinkor', id: 'NMF25'}
I want to console log the entire object but the id value should only contain the last three characters.
Like this:
{name: 'Flomo', age: 25, address: 'Sinkor', id: 'F25'}
I'm doing this:
console.log(Data.replace(/NM/g, ''))
But I got:
TypeError: Data.replace is not a function
Is there an easy way to achieve this?
replace is a method that operates on String, and doesn't change the string in-place.
If you're not worried about changing the original data, you can do this:
let Data = {name: 'Flomo', age: 25, address: 'Sinkor', id: 'NMF25'}
Data.id = Data.id.replace('NM', '')
console.log(Data);
Alternatively, if you're not sure what the first characters of the id will be (or how many there could be), you could do this:
let Data = {name: 'Flomo', age: 25, address: 'Sinkor', id: 'NMF25'}
Data.id = Data.id.substring(Data.id.length-3)
console.log(Data);
If you need to keep the original data intact, you can copy the object, however this can be complicated depending on the data that might be in the object: How do I correctly clone a JavaScript object?
The replace function works on a String. Youre calling that function on an Object.
You probably intended to call replace on the value of the property id. The terms I just used should help you mentally step thru problems like this in the future!
If you look at MDN's documentation for JavaScript, you'll see which functions you can call on which Types and other objects.

Javascript for-in loop issue

I'm doing codecademy right now and I'm having an issue with one lesson involving for-in loops. The requirement for thi exercise is to log "bill" and "steve to the console. However, I'm getting the entire array except those two strings logged instead. What's going on here?
var friends = {
bill: {firstName: "Bill",
lastName: "Ferny",
number: "452-556-5412",
address: ['One Bree Hill', 'Bree', 'Middle Earth', '00000']
},
steve: {firstName:"Steve",
lastName:"Rogers",
number:"805-223-5568",
address: ['1500 Settlers Court', 'Paso Robles', 'CA', '93446']
}
};
var list = function (friends) {
for (var p in friends) {
console.log(friends[p]);
}
};
list(friends);
change console.log(friends[p]); into console.log(friends[p].firstName);.
In a for-in loop, the variable is set to the property names. So if you want to log the property name, use console.log(p). friends[p] is the value that the property name maps to in the object.
You need to specify what you want even further.
This:
console.log(friends[p]);
should be changed to this:
console.log(friends[p].firstName);
Your code is only getting you all of the properties associated with friends[bill] and friends[steve]. You want their first names, so you have to use dot notation and add .firstName to the end of your console.log() statements.
As other people have noted, you can also use console.log(p) which logs the property name (so bill and steve), but since you are on Codecademy, I think they'll want you to use the first method I mentioned.

Categories

Resources