Hello I am very new to JavaScript and need some guidance. I am trying to build a reference for people in a club. I started by creating an array like so:
var People = ['Adam', 'Bruce', 'Steve']
But now I want to add characteristics to Adam, for instance height, weight, age, etc.
I want to be able to access information regarding people in my array by something like:
alert(People.Adam.height);
How would I structure it so that objects in my array has unique characteristics?
var people = [],
adam = {
height: 200,
weight: 200,
age: 20
};
people.push(adam);
console.log(people[0].height); // 200
or use object instead of array:
var people = {},
adam = {
height: 200,
weight: 200,
age: 20
};
people.adam = adam;
console.log(people.adam.height); // 200
You're currently adding strings into your array, not objects. You need to make your people into objects.
var adam = {
name: 'Adam',
height: 6.0
}
To retrieve Adam's height now, you'd call adam.height. So if you had an array, People, with adam (and others) inside, here's how you could do it:
var people = [adam]
alert(people[0].height)
// Alerts 6
Edit: alternatively, if you'd like to access Adam by name, you could make people an object instead of an array:
var people = {'adam' : adam}
alert(people.adam.height)
// Alerts 6
You can create an object, so you can access any nested property of that object:
var People = {
Adam: {
height: '187',
age: '22',
favorite_color: 'orange'
},
Paul: {
height: '156',
age: '38',
favorite_color: 'blue'
},
}
You need to make an object that have name of the people as key and the value for each key would be details for the person in form of an object. It could be something like
var People = {
"Adam" : {
"height" : "someValue",
"anotherParam" : "someOtherValue"
},
"Bruce" : {
"height" : "someValue",
"anotherParam" : "someOtherValue"
}
}
Use a class. It might look like this:
class Person {
constructor(height, weight, birth_year) {
this.height = height;
this.weight = weight;
this.birth_year = birth_year;
}
}
Related
Came across the concept of creating new object using spread syntax as below
const human = { age: 20 };
const john = { ...human };
john.age = 10;
console.log(human.age); // 20
console.log(john.age); // 10
As shown above human object get to retain it's original value. Now have a look at below code:
const human = { age: 20, cars: ["toyota", "honda"] };
const john = { ...human };
john.cars[1] = "camero";
console.log(human.cars); // ["toyota", "camero"]
console.log(john.cars); // ["toyota", "camero"]
Can anyone explain to me why the above scenario happened? Why human's cars object get changed? It looks to me that it's very likely for developer to make mistakes without understanding how to avoid the inconsistent behaviour
The object human only contains a reference to the array which contains ["toyota", "honda"]. When you duplicate the object using the spread operator, you also duplicate the reference, which means that john has an identical reference and therefore john.cars is the same array as human.cars.
Because of this, if you modify john.cars, you also modify human.cars because they are the same array. If you want to clone an array you can also do this using the spread operator:
const human = { age: 20, cars: ["toyota", "honda"] };
const john = { ...human };
john.cars = [ ... human.cars ];
john.cars[1] = "camero";
console.log(human.cars); // ["toyota", "honda"]
console.log(john.cars); // ["toyota", "camero"]
You will also see this type of behaviour if you clone an object that has properties which are objects:
const human = { name: { first: "John", last: "Jackson" } };
const human2 = { ... human };
human2.name.first = "Ellen";
console.log(human.name.first); // Ellen
That's because the spread operator only copies a reference to the name object, not the name object itself. Therefore, modifying one modifies the other because they are the same object. This is referred to as shallow cloning. If you want to avoid this confusion, you need to perform a deep clone.
The easiest way to do this is to convert to JSON and then convert back:
const human = { name: { first: "John", last: "Jackson" } };
const human2 = JSON.parse(JSON.stringify(human));
human2.name.first = "Ellen";
console.log(human.name.first); // John
console.log(human2.name.first); // Ellen
Is there any downside to using named arguments for functions in JavaScript and PHP. I don't see any downside. There's the fact that you need to extract them (though you don't absolutely have to I guess) - but you can use that as a way of using defaults. Eg.
Javascript:
function myFunction (opt)
{
var name = opt.name || 'Barry',
age = opt.age || 26,
eyes = opt.eyes || 'brown';
}
And call it like this:
myFunction ({
name: 'Fred',
age: 56,
eyes: 'pink'
})
PHP
function myFunction ($opt)
{
$name = $opt['name'] ? $opt['name'] : 'Barry';
$age = $opt['age'] ? $opt['age'] : 26;
$eyes = $opt['eyes'] ? $opt['eyes'] : 'brown';
}
EDIT: Maybe use the extract() function here to make things easier.
And call it like this:
myFunction ([
'name' => 'Fred',
'age' => 56,
'eyes' => 'pink'
])
In Javascript, you could use default values, like
function myFunction({ name = 'Barry', age = 26, eyes = 'brown'} = {}) {
console.log(name, age, eyes);
}
myFunction();
myFunction({ name: undefined, age: 30 });
myFunction({ name: 'jane', age: 35, eyes: 'blue' });
Is there any downside to using named arguments for functions in JavaScript and PHP
Just one. Neither PHP nor JavaScript support named arguments.
EDIT
Here wiki page on what named arguments really is, as many seem to get the concept wrong.
You are talking about an options object, not named arguments. Named arguments are not available in JavaScript, and would look something like this following line. Note that the parameters are not inside an object:
myFunction( name: 'Fred', age: 56, eyes: 'pink' );
Using an options object rather than individual function parameters is useful if there are more than a few arguments to pass. The object doesn't have to worry about ordering, or whether elements are optional.
ES2015 supports destructuring and defaults, which can simplify this even more, though the formatting may look very different at first...
function myFunction ({ name = 'Barry', age = 26, eyes = 'brown'})
{
console.log(name, age, eyes);
}
This function will throw an error if an object is not passed, but it can accept an empty object, or one with any number of those keys. As Nina's answer shows, you would need another default to prevent that error:
function myFunction ({ name = 'Barry', age = 26, eyes = 'brown'} = {})
{
console.log(name, age, eyes);
}
I'm trying to create a script that will insert some values in to an object.
I basically want to end up with a series of objects that would look something like this -
myObj.data.person[0].name = 'name 1';
myObj.data.person[1].name = 'name 2';
myObj.data.person[2].name = 'name 3';
etc
Here is my object which contains an array of objects.
var addressBook = {
data: [
person = {
name: '',
address: ''
}
]
}
And a for loop to insert repeating information.
for (i=0; i < 10; i++)
{
myObj.data.person[i] = {name: 'Joe Bloggs', address: 'Main Street'};
console.log(myObj.data.person.name);
}
Whenever I run this code I get the following error -
Uncaught TypeError: Cannot set property 'person' of undefined at <anonymous>:14:24
So, the question is where am I going wrong ? And furthermore would this be considered the right way to go about creating a list of Objects (e.g. Person 1, Person 2 etc)?
(I'm ultimately thinking of how I can create something like a Person constructor and use a loop to create multiple Person objects).
Thanks,
Please try to change your object notation in following way
var addressBook = {
data: [{
name: '',
address: ''
},
{
name: 'Roshan',
address: ''
},
{
name: 'Roshan1',
address: ''
}
]
}
try this :
myObj.data[i].person = 'John';
myObj.data[i].address = 'NYC';
See this Answer as addendum to isetty ravitejakumar's Answer
You should consider writing a prototype / class for your usecase.
In this case you could keep better track of your data.
maybe something like this:
var AddressBook = {},
Person = {};
(function() {
AddressBook.prototype = {
data: [],
add: function(person) {
this.data.push(person);
}
};
Person = function(name, address) {
this.name = name;
this.address = address;
}
Person.prototype = {
name,
address
};
})();
var people = [
{firstName : "Thein", city : "ny", qty : 5},
{firstName : "Michael", city : "ny", qty : 3},
{firstName : "Bloom", city : "nj", qty : 10}
];
var results=_.pluck(_.where(people, {city : "ny"}), 'firstName');
For example : I need firstName and qty.
To project to multiple properties, you need map, not pluck:
var results = _.map(
_.where(people, {city : "ny"}),
function(person) {
return { firstName: person.firstName, qty: person.qty };
}
);
[{"firstName":"Thein","qty":5},{"firstName":"Michael","qty":3}]
(Fiddle)
Note that, if you wanted to, you could create a helper method "pluckMany" that does the same thing as pluck with variable arguments:
// first argument is the source array, followed by one or more property names
var pluckMany = function() {
// get the property names to pluck
var source = arguments[0];
var propertiesToPluck = _.rest(arguments, 1);
return _.map(source, function(item) {
var obj = {};
_.each(propertiesToPluck, function(property) {
obj[property] = item[property];
});
return obj;
});
};
You can use the _.mixin function to add a "pluckMany" function to the _ namespace. Using this you can write simply:
var results = _.chain(people).where({city : "ny"}).pluckMany( "firstName", "qty").value();
(Fiddle)
TL;DR Use :
var results = _.chain(people)
.where({ city: "ny" })
.map(_.partialRight(_.pick, 'firstName', 'qty'))
.value();
But please read on for explanations as I feel the process of finding this solution is more interesting than the actual answer.
The general pattern would be (it works with lodash too) :
_.map(array, function(obj) { return _.pick(obj, 'x', 'y', 'z'); });
Given this general map function which transforms each element of a collection, there are multiple ways to adapt this to your particular situation (that vouch for the flexibility of map, which is a very basic building block of functional programs).
Let me present below several ways to implement our solution :
var _ = require('lodash'); // #lodash 2.4.1 at the time of writing
// use underscore if you want to, but please see http://stackoverflow.com/questions/13789618/differences-between-lodash-and-underscore
/* la data */
var people = [{
firstName: "Thein",
city: "ny",
qty: 5
}, {
firstName: "Michael",
city: "ny",
qty: 3
}, {
firstName: "Bloom",
city: "nj",
qty: 10
}];
/* OPTION1 : mixin' with _ */
_.mixin({
pluckMany: function() {
var array = arguments[0],
propertiesToPluck = _.rest(arguments, 1);
return _.map(array, function(item) {
/* Alternative implementation 1.1
* ------------------------------
* Taken from #mMcGarnagle answer
* _each is easy to understand here,
* but has to modify the variable `obj` from a closure
* I try to avoid that for trivial cases like this one.
*/
var obj = {};
_.each(propertiesToPluck, function(property) {
obj[property] = item[property];
});
return obj;
/* Alternative implementation 1.2
* ------------------------------
* Rewrite the previous code,
* by passing the accumulator (previously`obj`, but really it is an object that accumulates the result being constructed) across function calls.
* This construction is typical of the `reduce` function, closer to a functionnal programming style.
*/
return _.reduce(propertiesToPluck, function(obj, property) {
obj[property] = item[property];
return obj;
}, {});
/* Alternative implementation 1.3
* ------------------------------
* If we are already using lodash/underscore,
* then let's use the `pick` function ! I also included an example of `flatten` here
*/
return _.pick(item, _.flatten(propertiesToPluck, true));
/* Alternative implementation 1.4
* ------------------------------
* But really flatten is not needed.
*/
return _.partial(_.pick, item).apply(null, propertiesToPluck);
});
}
});
/* Let's use our mixed function !
* Since we call several _ functions on the same object
* it is more readable to chain the calls.
*/
var results = _.chain(people)
.where({
city: "ny"
})
.pluckMany('firstName', 'qty')
.value();
/* OPTION 2 : without mixing our code with lodash/underscore */
var results = _.chain(people)
.where({
city: "ny"
})
.map(_.partialRight(_.pick, 'firstName', 'qty'))
.value();
console.log(results);
If you like this way of writing code with underscore or lodash, I highly suggest that you have a look at functional programming, as this style of writing as well as many functions (map, reduce amongst many others) come from there.
Note : This is apparently a common question in underscore :
https://github.com/jashkenas/underscore/issues/1104
This is apparently no accident if these are left out of underscore/lodash : "composability is better than features". You could also say do one thing and do it well. This is also why _.mixin exists.
Yep, I wish pluck had an option of passing an array, but in the meantime, you could do:
const pluckFields = (arr, fields) => _.map(arr, item => _.pick(item, fields))
My understanding is the author of the question wants to take an array of objects with many properties and strip each object down to a small list of properties.
There are myriad ways of doing so with _ , but I like this way best. Pass in an empty result object which will be "this" inside the function. Iterate with _each , and _pick the fields you want:
var myObjects = [
{ "first" : "eric",
"last" : "gumbo",
"code" : "x482"
},
{ "first" : "john",
"last" : "dinkman",
"code" : "y9283"
}
];
var result = [];
_.each( myObjects, function(itm) { this.push(_.pick(itm,"first","code")) }, result );
console.log(result);
YAAUu-Yep Another Answer Using underscore...
// use a proper browser to run this code snippet, a browser that is es6-compliant
let people = [{
firstName: "Thein",
city: "ny",
qty: 5
},
{
firstName: "Michael",
city: "ny",
qty: 3
},
{
firstName: "Bloom",
city: "nj",
qty: 10
}
];
// either you pick the properties you want
let picking = _.iteratee((person) => _(person).pick("firstName", "city"));
// either you omit the properties you do not want
let omitting = _.iteratee((person) => _(person).omit("qty"));
// create the filter by city
let living = (people, city) => _(people).where({
"city": city
});
// put the "filter by city" into a mixin (as I assume it would be used again & again)
_.mixin({
living: living
});
// do the thing (twice),
// these chaining methods could be done into a mixin as well
console.log("results by picking properties:", _(people).chain().living("ny").map(picking).value());
console.log("results by omitting properties:", _(people).chain().living("ny").map(omitting).value());
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
That one linear might save some lines:
var results=_.pick(_.where(people, {city : "ny"}), 'firstName', 'qty');
We don't have to use pluck, omit do the trick as well.
var result = _.map(people, function(person) {
return _.omit(person, 'city');
});
I want to create some custom javascript objects some of which have properties which are other objects. I'm not sure what the syntax would be to do this. My pseudo code is below with the idea that I have a person object and an order object. The order object has a property that I want to be of the person object type. Is this possible in javascript and if so, can someone give me a basic example? Thanks.
var person {
name: "John",
gender: "M",
age: 3
}
var order {
customer: person, /*the property name is customer but of type person - is this possible?*/
total: 100
}
Consider constructors:
function Person( name, gender, age ) {
this.name = name;
this.gender = gender;
this.age = age;
}
function Order( customer, total ) {
this.customer = customer;
this.total = total;
}
Usage:
var person1 = new Person( 'John', 'M', 3 );
var order1 = new Order( person1, 100 );
The constructors act as classes. You invoke them via new to create new instances (persons and orders).
You were almost correct; all you need is to include some '='
var person = {
name: "John",
gender: "M",
age: 3
}
var order = {
customer: person, /*the property name is customer but of type person - is this possible?*/
total: 100
}
You could do this:
var person = {
name: "John",
gender: "M",
age: 3
};
var order = {
customer: person,
total: 100
};
This also passes in JSLint. You were missing '=' signs.
You code is nearly fine (missing the = to assign the anonymous object to the variable):
var person = {
name: "John",
gender: "M",
age: 3
};
var order = {
customer: person, /*the property name is customer but of type person - is this possible?*/
total: 100
};
http://jsfiddle.net/D7u3x/
Sure, thats pretty much it. Your syntax is a little off, but only slightly.
Here is your example: jsfiddle