How to call for object keys in javascript (codecademy) - javascript

I'm following an online course in Javascript from Codecademy but i'm stuck in an assignment.
I'm trying to list the firstName key from my "friends list".
I have to do this with a "for in" statement in a function.
The firstName key is within the object "Steve", which in in an object "Friends".
This is the code that i have at the moment:
var friends = {
steve: {
firstName: 'Steve',
lastName: 'Jobs',
number: '1',
address: ['Fregataan','65','8546','RG','Amsterdam','The Netherlands'],
},
bill: {
firstName: 'Bill',
lastName: 'Gates',
number: '2',
address: ['Fregataan','665','8546','RG','Amsterdam','The Netherlands'],
},
};
function list(friends){
for (var firstName in friends){
console.log(friends.keys(firstName))
}
}
list(friends.keys);
This is the assignment I get from the course:
1. Create a function list that takes a single parameter.
2. In the body of the function, write a for/in loop.
3. In the loop, use console.log to print out the key. (For example, if you only have bill and steve as entries, list should just print out "bill" and "steve".)
The object "friends" was already written in a previous assignment. The function has to be written in this assignment. Can someone please find my mistake and tell me what i did wrong?
Greetings,
Luuk

I think it might be a tricky question. You are trying to print the firstName key which (if done correctly) will print out "Steve" and "Bill", but the assignment, as you described it, is to print out the key (i.e. "steve" and "bill"). So if that's the case, you should just print out the key:
function list(friends){
for (var key in friends){
console.log(key);
}
}
Hope this helps.

You should play around with it a bit more.
No need to use 'keys'.
var friends = {
steve: {
firstName: 'Steve',
lastName: 'Jobs',
number: '1',
address: ['Fregataan','65','8546','RG','Amsterdam','The Netherlands'],
},
bill: {
firstName: 'Bill',
lastName: 'Gates',
number: '2',
address: ['Fregataan','665','8546','RG','Amsterdam','The Netherlands'],
},
};
function list(friends){
console.log(friends);
for (var friend in friends){
console.log(friend);
var f = friends[friend];
console.log(f.firstName);
}
}
list(friends);

Related

Remove element from objects in javascript multidimensional array

I have read several solutions to this problem here. When I try it, I continue to receive an error for the pop() method.
I have what is essentially a multidimensional array in javascript.
I am tasked with returning the array with the sensitive info removed (e.g. remove the SSN, in this example)
I thought I could use a foreach loop, and the pop() function to remove the last element of the child arrays, the SSN.
testing it using node on the commandline, the stdout is telling me that element.pop() is not a function. i've tried it with pop(), slice(), filter(), all with no success.
when running $> node filename.js
H:\Apache2\htdocs\test\filename.js:50
noppi[i] = element.pop();
^
TypeError: element.pop is not a function
let recs = [
{
ID: 1,
NAME: 'John',
EMAIL: 'john#example.com',
SSN: '123'
}, {
ID: 2,
NAME: 'Sally',
EMAIL: 'sally#example.com',
SSN: '456'
}, {
ID: 3,
NAME: 'Angie',
EMAIL: 'angie#example.com',
SSN: '789'
}
];
let i = 0;
let noppi = [];
recs.forEach(element => {
noppi[i] = element.pop();
i++;
});
console.log(noppi);
At the risk of sounding redundant, I'll briefly reiterate what the earlier answers have already stated.
The input data structure isn't a multi-dimensional array [ [ ... ], [ ... ] ] , it's an array of objects [ {...}, {...} ]. So you can't use Array methods like .pop() on the objects {...}.
Here's a simple one-liner that uses .forEach() and delete.
recs.forEach(obj => delete obj.SSN)
delete is an operator with one purpose: to remove an object's property like for example SSN: '123-45-6789'. Simple and perfect.
Note, .forEach() mutates the array, meaning that it's the original data being changed (see Minja's comment).
let recs = [
{
ID: 1,
NAME: 'John',
EMAIL: 'john#example.com',
SSN: '123'
}, {
ID: 2,
NAME: 'Sally',
EMAIL: 'sally#example.com',
SSN: '456'
}, {
ID: 3,
NAME: 'Angie',
EMAIL: 'angie#example.com',
SSN: '789'
}
];
recs.forEach(obj => delete obj.SSN);
console.log(recs)
Try this:
recs.forEach(element => {
noppi.push = element;
});
You are trying to use pop() on an object not an array
As per your need you need to remove SSN from your object, try below code it should work for you.
recs.forEach(element => {
const { SSN, ...rest } = element;
noppi.push(rest);
});
Here we are removing SSN from object and rest will push in noppi.

Array of objects which have all the same properties

I was wondering, if it's possible to ensure with Angular 12 / Typescript, that all objects within an array have the same properties, without declaring the properties explicitly (should be generic).
Here's an example of what I want to achieve:
// This should compile because all objects have the same properties
const correct = [
{firstname: 'Jack', lastname: 'Sanders'},
{firstname: 'Susanna', lastname: 'Marsaglia'},
{firstname: 'Walter', lastname: 'Walker'}
]
// This shouldn't compile because some object have different properties
const wrong = [
{firstname: 'Aline', lastname: 'Rose', phone: 'xxx-xxx-xx-xx'},
{firstname: 'Daniel', email: 'dan#gmail.com'},
{firstname: 'Louisa', email: 'louisa#icloud.com'}
]
I was able to create an Interface which only allows properties with type string, but I couldn't achieve the example above.
export interface Data {
[keys: string]: string
}
Update (Use-Case)
I need this check in a service which exports data. You should be able to pass an array of objects, which represent rows within a table.
For example:
const data = [
{firstname: 'Jack', lastname: 'Sanders'},
{firstname: 'Susanna', lastname: 'Marsaglia'},
]
this.exportService.export(data);
This code would generate a file with a table like this:
firstname
lastname
Jack
Sanders
Susanna
Marsaglia
The service should support any passed data, because it's used widely over our entire application. But to be sure that the service can export the data to a table, we need to ensure, that all passed objects have the same properties (e.g. columns).
function sameKeys(input) {
if (!input || input.length === 0) return;
const keys = new Set(Object.keys(input[0]));
return input.every((item) => Object.keys(item).every((key) => keys.has(key)));
}
If you want a compile time check, then doing a proper type definition makes sense have given in another answer. But that will only work if this data is hardcoded. if you are fetching it from backend it will not work as types are lost when the code is already build as javascript don't have types.
You can very well make your exportservice generic, ie something like this
class ExportService {
public export<T>(data: T[]) {
console.log(data);
}
}
Or you can also just use {[key:string]:string} as element type in you export service
class ExportService {
public export(data: {[key:string]:string}[]) {
console.log(data);
}
}
That doesn't hinder you from defining the type of your data correctly.
const data: { firstname: string, lastname: string}[] = [
{ firstname: "john", lastname: "foo"},
{ firstname: "jim", lastname: "bar"}
];
this.exportservice.export(data);
See also this fiddle
const data = [
{firstname: 'Jack', lastname: 'Sanders'},
{firstname: 'Susanna', lastname: 'Marsaglia'},
{firstname: 'Walter', lastname: 'Walker'}
]
const dataReference : Required<typeof data[number]>[] = data
You should achieve this by interface as below
interface IStructure {
firstname: string;
lastname: string;
}
const correct: Array<IStructure> = [
{firstname: 'Jack', lastname: 'Sanders'},
{firstname: 'Susanna', lastname: 'Marsaglia'},
{firstname: 'Walter', lastname: 'Walker'}
];
//wrong will throw error

call() is not working with getter and setter in javascript

let Name = {
get fullname() {
return this.fname + this.last
}
}
function pension() {
return this.age > 60
}
let firstclass_employee = [{
fname: "sangeth",
last: "AV",
age: 21,
address: {
housename: "good house",
place: "goodplace",
city: "goodtwon",
postcode: 121212
},
hobbies: ["driving", "travelling", "sports"]
}, {
fname: "ramu",
last: "kv",
age: 29,
address: {
housename: "etho veedu",
place: "vayadi",
city: "kalur",
postcode: 11111
},
hobbies: ["travelling", "sports"]
}]
console.log(" objects::\t", Name, "\n", firstclass_employee)
//calling a out side function for an object(out side function may be inside an object oe not)
console.log("Fullname of first employee::", Name.fullname.call(firstclass_employee[0]))
console.log("Pension status of of first emlpoyee::", pension.call(firstclass_employee[0]))
console.log("Fullname of 2nd employee::", Name.fullname.call(firstclass_employee[1]))
console.log("Pension status of of 2nd emlpoyee::", pension.call(firstclass_employee[1]))
AND getting error--->
console.log("Fullname of first employee::", Name.fullname.call(firstclass_employee[0]))
^
TypeError: Name.fullname.call is not a function
remove get - which is not a valid here
let Name = {
fullname() {
return this.fname + this.last
}
}
If you want regular function remove the get and it will work fine. Sorry, I was mistakenly said you have errors in the console.log() part.
let Name = {
fullname() {
return this.fname + this.last
}
}
function pension() {
return this.age > 60
}
let firstclass_employee = [{
fname: "sangeth",
last: "AV",
age: 21,
address: {
housename: "good house",
place: "goodplace",
city: "goodtwon",
postcode: 121212
},
hobbies: ["driving", "travelling", "sports"]
}, {
fname: "ramu",
last: "kv",
age: 29,
address: {
housename: "etho veedu",
place: "vayadi",
city: "kalur",
postcode: 11111
},
hobbies: ["travelling", "sports"]
}]
console.log(" objects::\t", Name, "\n", firstclass_employee)
//calling a out side function for an object(out side function may be inside an object oe not)
console.log("Fullname of first employee::", Name.fullname.call(firstclass_employee[0]))
console.log("Pension status of of first emlpoyee::", pension.call(firstclass_employee[0]))
console.log("Fullname of 2nd employee::", Name.fullname.call(firstclass_employee[1]))
console.log("Pension status of of 2nd emlpoyee::", pension.call(firstclass_employee[1]))
As far as why the call() is invalid is that Name.fullname is not exposed as a function. It is exposed the same way as a field would be, e.g.
const Name = {
fullname: 'Bob'
};
With that structure, you wouldn't expect to be able to call Name.fullname.call, right? But for the purposes of getting the value, that's what the prior code exposed to the outside world (the difference with the field being that you can set the value, whereas with a getter and no setter, the property is read only).
The get essentially tells the JavaScript engine that, whenever someone asks for the value of fullname, give them the value of the fname and last properties concatenated together.
Thus, when you ask for Name.fullname.call(firstclass_employee[0]) it first finds Name. Then it asks for the value of fullname. It gets back NaN, because this is the Name object and it doesn't have fname or last properties, and it tries to coerce the first undefined (from this.fname) to a Number for the addition operator, and gets NaN. Then it tries to get the call function on NaN, and there is no such thing, so it throws an error.
It appears as though you want to be able to get a full name from any object that has fname and last properties. I would suggest using static method for that rather than an instance property getter.
Similarly, a static method would work for determining employees who get a pension.
Personally, I would just create a class or series of classes that I could compose together to bring this functionality together, rather than trying to use call, but that's me.
const Name = {
fullName(obj) {
return `${obj.fname} ${obj.last}`;
}
};
const Pay = {
getsPension(obj) {
return obj.age > 60;
}
}
let firstclass_employee = [{
fname: "sangeth",
last: "AV",
age: 21,
address: {
housename: "good house",
place: "goodplace",
city: "goodtwon",
postcode: 121212
},
hobbies: ["driving", "travelling", "sports"]
}, {
fname: "ramu",
last: "kv",
age: 29,
address: {
housename: "etho veedu",
place: "vayadi",
city: "kalur",
postcode: 11111
},
hobbies: ["travelling", "sports"]
}]
console.log('should be sangeth AV: ', Name.fullName(firstclass_employee[0]));
console.log('should be false: ', Pay.getsPension(firstclass_employee[0]));

Advanced Destructuring of objects in ES6

I have the following object:
personObj = {
_id : '123',
first_name: 'John',
last_name: 'Doe',
}
I would like to destructure it to the following variables:
id, <-- _id
name: {
first, <-- first_name
last <-- last_name
}
(I want first_name and last_name to reside inside a 'name' object)
I've tried the following syntax:
const {
id: _id,
name: {
first: first_name,
last: last_name
}
} = personObj
However this causes an error.
What am I doing wrong?
Update
Chapter 10. Destructuring of book "Exploring ES 6" provides many advanced examples of how to use destructuring and explains how it works internally.
Destructuring can extract values directly into the properties of an object. The properties are not required to exist but all destination objects must already exist when the destructuring assignment happens.
Armed with this knowledge, the code that answers the question is:
let personObj = {
_id: '123',
first_name: 'John',
last_name: 'Doe',
}
// Create the objects that receive the values on destructuring
let c = { name: {} }
// Do the magic
({ _id: c.id, first_name: c.name.first, last_name: c.name.last } = personObj)
console.log(c)
// {id: "123", name: {first: "John", last: "Doe"}}
The parentheses around the assignment expression that uses destructuring are required, without them the engine reports a syntax error at the first :.
The original answer follows. It doesn't completely answer the question but I leave it here for reference. It shows how to use the rest properties (...) in destructuring expressions and it was accepted by the OP, as incomplete as it is.
The original answer
Destructuring with properties renaming works the other way around: the original name is placed before the colon, the new name is after it.
let personObj = {
_id: '123',
first_name: 'John',
last_name: 'Doe',
}
// Destructure personObj using different names for the properties
const {
_id: id,
first_name: first,
last_name: last
} = personObj
console.log('id: ' + id);
console.log('first: ' + first);
console.log('last: ' + last);
// Output
// id: 123
// first: John
// last: Doe
You can then assemble the pieces (id, first, last) into a new object:
let c = {
id,
name: {
first,
last
}
}
console.log(c);
// Output
// { id: '123', name: { first: 'John', last: 'Doe' } }
Update
The most similar result to what you describe in the question can be achieved by:
let { _id: id, ...name } = personObj
console.log(id)
console.log(name)
// Output
// 123
// { first_name: 'John', last_name: 'Doe' }
But this way the properties of name use the same names they have in personObj. Even more, it doesn't work any more if you add to personObj properties after last_name that you don't want to copy in name.

Javascript resulting in SyntaxError: Unexpected identifier

I am learning Javascript on Codecademy, and after entering in my code to make a short contact list, it returns an error message of:
SyntaxError: Unexpected identifier
Here is my code:
var friends = {
var bill: {
firstName: "Bill",
lastName: "Gates",
number: "1800 4 charity",
};
var steve: {
firstName: "Steve",
lastName: "Jobs",
number: "1800 I have lots of jobs",
};
};
Any help is greatly appreciated thanks :)
You don't need var if you are in an object. Also be sure to get rid of trailing commas.
var friends = {
bill: {
firstName: "Bill",
lastName: "Gates",
number: "1800 4 charity"
},
steve: {
firstName: "Steve",
lastName: "Jobs",
number: "1800 I have lots of jobs"
}
};
When dealing with JSON remember you are just creating lists of names and values.
The format is
var object = {
nameOfProperty: value,
nameOfAnotherProperty: value2
};
Remember you only need commas between values not at the end of the list and no semicolons within the object (because then JS thinks you're missing the rest!).
The tricky part is then objects within Objects but as you're exploring, using an object as a value is perfectly legal. So start with the innermost objects and work your way out and you shoudl be fine.

Categories