I want to know the second argument of application - javascript

function printProfile(name, age, ...args) {
return `${this.type} ${name} Age:${age}${args.length === 0 ? '' : ' ' + this.feature + ':' + args.join(',')}`
}
const developer = {
type: 'Developer',
feature: 'Language'
};
const artist = {
type: 'Artist',
feature: 'Song'
};
printProfile.apply(developer, ? ) // --> 'Developer jack Age:30'
printProfile.apply(developer, ? ) // --> 'Developer jin Age:20 Language:JavaScript'
printProfile.apply(artist, ? ) // --> 'Artist BTS Age:7 Song:ON,Dynamite'
The second argument is '?'. I wonder what it is.

The second parameter of the apply is an array of items that will match the position of your function arguments. And any left over goes to the args param. Here is one example, and from this you should be able to grasp the concept to figure out the rest.
printProfile.apply(developer, ['Joe', 34, 'JavaScript'])
Resources
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
Test Snippet
function printProfile(name, age, ...args) {
return `${this.type} ${name} Age:${age}${args.length === 0 ? '' : ' ' + this.feature + ':' + args.join(',')}`
}
const developer = {
type: 'Developer',
feature: 'Language'
};
const artist = {
type: 'Artist',
feature: 'Song'
};
const result = printProfile.apply(developer, ['Joe', 34, 'JavaScript'])
console.log(result)

Related

Why doesn't console.log() of a map object return the data?

I have pet data stored on as a mongodb object as shown below:
{
"_id" : ObjectId("0000439359317900131f111"),
"name" : "Travis",
"description" : "Travis is a support animal",
"petId" : "225123",
"petDetails" : {
"color" : "brown"
}
}
When I try to console.log petDetails (petDetails is a map) object using the following:
const pet = await context.AnimalService.findOne({where:{_id : userSubscription.planId}})
const petDetails = pet.petDetails
console.log('Logging Pet Details', petDetails)
The result is returned as:
Logging Pet Details {
'$__parent': '{\n' +
' _id: 0000439359317900131f111,\n' +
" name: 'Travis',\n" +
" description: 'Travis is a support animal',\n" +
" petId: '225123',\n" +
" petDetails: Map(1) { 'color' => 'brown' },\n" +
' __v: 0,\n' +
'}',
'$__path': 'petDetails',
'$__schemaType': '[object Object]'
How can have petDetails simply returned as an object and not the weird way it is currently formatted?
maybe your petDetail is Mongo object, you should convert it to plain object by using petDetail.toObject
Ref: https://stackoverflow.com/a/7503523/1743046

How to simplify object

I have an issue here where the code is quite heavy and quite hard to read imo.
I've simplified the code as much as I can but I was wandering if there's a way to simplify this code even further? Or maybe if there is any better terminology i could use for the comments? Any help is much appreciated, Thanks in advance!
const hourly = rateType[1] === 'Hourly';
const daily = rateType[1] === 'Day Pass';
const monthly = rateType[1] === 'Monthly Pass';
const single = passType === 'single';
// -- For all payloads
const data = {
booking_name: username.first_name + ' ' + username.last_name,
number_of_people: numOfPeople,
};
// -- Hourly payload
const hourlyPayload = {
...data,
date: moment(mainDate).format('YYYY-MM-DD'),
from: moment(timeFrom).format('hh:mm'),
to: moment(timeUntil).format('hh:mm'),
};
// -- Daily or monthly payload
const DayOrMonthPayload = {
...data,
start_date: moment(startDate).format('YYYY-MM-DD'),
end_date: moment(endDate).format('YYYY-MM-DD'),
};
// -- Single day payload
const singleDayPayload = {
...data,
dates: [moment(startDate).format('YYYY-MM-DD')],
};
// -- // CREATE_BOOKING_FN // -- //
if (rateType) {
setLoading(true);
hourly // --||-- Hourly Action --||-- \\
? await addToCart(hourlyPayload, 'hourly', id, cartItems, () =>
_handleAdded(
fastCheckout ? fastCheckout : null,
cb ? () => cb() : null,
),
)
: daily // --||-- Daily Action --||-- \\
? await addToCart(
single ? singleDayPayload : DayOrMonthPayload,
single ? 'individual-dates' : 'daily',
id,
cartItems,
() =>
_handleAdded(
fastCheckout ? fastCheckout : null,
cb ? () => cb() : console.log('null'),
),
)
: monthly // --||-- Monthly Action --||-- \\
? await addToCart(DayOrMonthPayload, 'monthly', id, cartItems, () =>
_handleAdded(
fastCheckout ? fastCheckout : null,
cb ? () => cb() : console.log('null'),
),
)
: null;
setLoading(false);
} else {
alert('Please select a rate');
}
You can use Template Strings to simplify booking_name
booking_name: `${username.first_name} ${username.last_name}`,
Also consistency in variable names would better, you could choose one of the variable naming styles, snake_case or camelCase.
Also now you can shorten expression key:value even more.
const data = {
booking_name: `${username.first_name} ${username.last_name}`,
number_of_people,
};
Also that ternary expression is very hard to read, I think switch case would better.
switch (type_of_date) {
case hourly:
...
case daily:
...
case monthly:
...
default:
...
}
I would recommend using functions for avoiding repetition and creating data. Here we have a basic Booking object that can be used to construct all varieties of bookings. Fill in ___ as you see fit -
function Booking(type, ___) {
switch (type) {
case "Hourly"
return { ...Party(___), ...Hourly(___) }
case "DayOrMonth":
return { ...Party(___), ...DayOrMonth(___) }
case Single:
return { ...Party(___), ...Single(___) }
default:
throw Error("invalid booking type: " + type)
}
}
In the function above it's plain to see that each output has Party information associated -
function Party(user, number_of_people) {
return {
name: user.first_name + " " + user.last_name
number_of_people
}
}
Here are the booking types, Hourly, DayOrMonth and Single -
function Hourly(date, from, to) {
return {
date: mDate(date),
from: mTime(from),
to: mTime(to)
}
}
function DayOrMonth(start, end) {
return {
start: mDate(start),
end: mDate(end)
}
}
function Single(date) {
return {
date: mDate(date)
}
}
We avoid repetition of moment(...).format(...) and ensure consistency with mDate and mTime -
function mDate(t) {
return moment(t).format("YYYY-MM-DD")
}
function mTime(t) {
return moment(t).format("hh:mm")
}

Convert a string into an array of objects

Currently I have this string:
"Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
How do I separate it into a an array of object that looks like this:
[
{ type: 'string', value: 'Hello, I'm ' },
{ type: 'token', value: 'first' },
{ type: 'string', value: ' ' },
{ type: 'token', value: 'last' },
{ type: 'string', value: ', and I <3 being a ' },
{ type: 'token', value: 'occupation' },
{type: 'string', value: 'I am > blah'}
]
The pattern of the string is that if we find a word that looks like this: <%word%>, then we put that into the array as an object with type token. Otherwise we put it in as a type string. My question is how do we implement it in code.
I'm having difficulty with forming the phrase which is going to be the value for the key value. Below is a code that I tried to implement, but it is faulty.
My idea is to have a word variable, which is empty, and as it goes through the string it concats the words to form the phases. Once it see that it's in between <% and %>, it will be given a type token and push into the arrStr array.
However 2 issues: 1) It seems that with this code, each iteration of the string from "H" to "He" to "Hel" to "Hell" to "Hello" is being generated. 2) It seems like it never touches token. 3) The first "h" in "hello" is somehow omitted.
How do I do this without using regex?
Using Replace Twice
Let's replace the angular brackets using some dummy string to split the data easily.
So, we replace <% by *# and %> only by *.
Then we split the data by only *. And after splitting we have the following array
[
"Hello, I'm ",
"#first",
" ",
"#last",
", and I <3 being a ",
"#occupation",
". I am > blah",
]
So, the extra # that we added to only the opening angular bracket will help us differentiate a token from a string.
Now we can simply map this array and get the desired result.
NOTE: You can use an appropriate dummy string that you're sure won't appear in the string.
const
str = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah",
res = str
.replace(/<%/g, "*#")
.replace(/%>/g, "*")
.split("*")
.map((v) =>
v[0] === "#"
? { type: "token", value: v.slice(1) }
: { type: "string", value: v }
);
console.log(res);
var str = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
var arr = str.split('<%');
var final = [], vala, thetype;
arr.forEach(val => {
vala=val.split('%>');
thetype='string';
if (vala.length>0) thetype='token';
final.push({type: thetype, value: vala[0]});
})
I'm sure regex will be a better solution, but I don't know it. So here is my approach:
let txt = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
var arr = [];
txt.split("<%").forEach(x => {
if (x.includes("%>")) {
x.split("%>").forEach((y, i) => {
arr.push({type: i == 0 ? 'token' : 'string', value: y});
})
} else {
arr.push({type: 'string', value: x});
}
});
console.log(arr);
Using regex:
const convertToObjectArr = (str = '') => {
const reg = /<%(.*?)%>/g;
let arr = [];
let index = 0, lastIndex = 0;
while (match = reg.exec(str)) {
index = match.index;
if(index > lastIndex) {
arr.push({ type: 'string', value: str.substring(lastIndex, index) });
}
lastIndex = reg.lastIndex;
arr.push({ type: 'token', value: str.substring(lastIndex-2, index+2) });
}
if (lastIndex == 0) {
arr.push({ type: 'string', value: str.substring(lastIndex) });
} else if (lastIndex < str.length) {
arr.push({ type: 'token', value: str.substring(lastIndex) });
}
return arr;
}
console.log( convertToObjectArr("Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah") );
console.log( convertToObjectArr("Hello") );
console.log( convertToObjectArr("Hello, I'm <%first%>") );
You could parse the string with a regexp like this:
const input = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
const regex = /<%([^%]+)%>/g;
let result;
let parsed = [];
let lastIndex = 0;
while(result = regex.exec(input)) {
const { 1: match, index } = result;
parsed.push({ type: 'string', value: input.substring(lastIndex, index) });
parsed.push({ type: 'token', value: match });
lastIndex = index + match.length + 4;
}
parsed.push({ type: 'string', value: input.substring(lastIndex) });
console.log(parsed);
Here was my approach. You could simplify this a lot if you used regex (this is basically the exact use case for regex)
target = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah"
const split = (el) => {
const parts = el.split('%>')
return [{type: 'token', value: parts[0]}, {type: 'string', value: parts[1]}]
}
const parts = target.split('<%')
.map(el =>
el.indexOf('%>') === -1
? {type: "string", value: el}
: split(el)
).flat()
console.log(parts)
You can use a lexer to tokenize your string. I have used moo in this example:
const lexer =
moo.compile({ token: {match: /<%.+?%>/, value: raw => raw.slice(2, -2)}
, strlt: /.+?(?=<%)/
, strrt: /(?<=%>).+/ });
lexer.reset("Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah");
console.log(
[...lexer].map(({ type, value }) =>
({ type: (type === 'token' ? type : 'string')
, value }))
);
<script src="https://unpkg.com/moo#0.5.1/moo.js"></script>

How to wait created variable to change before rendering data in vue?

I have a variable that is called "name" inside my data(). And this is updated once I fetch this value from firebase using created() like this:
created: async function fetchDataFromFirebase() {
this.email = this.getCurrentUser().email
await this.doctorsCollection.doc(this.email).get().then(async (doc) => {
this.name = await doc.data().title + ' ' + await doc.data().firstName + ' ' + await doc.data().lastName
this.speciality = await doc.data().speciality
this.phone = await doc.data().phone
this.profilePicture = doc.data().img == null || doc.data().img === '' ? 'https://firebasestorage.googleapis.com/v0/b/healthy-wo.appspot.com/o/doctors%2FMantraHW-T-Coral-01.png?alt=media&token=2ae855cb-c96d-4b97-b813-c844f9e0e871':doc.data().img
// getCurrentAge will give the difference in years between today and the Date object you're passing
this.age = this.getCurrentAge(new Date((await doc.data().birthDate).toMillis())) + ' años'
// memberDate is a variable that holds the date this user was registered but in Date object format
let memberDate = new Date((await doc.data().subscriptionStart).toMillis())
this.member_duration = memberDate.getDate() + '/' + (memberDate.getMonth()+1<10 ? '0'+(memberDate.getMonth()+1):memberDate.getMonth()+1) + '/' + memberDate.getFullYear()
})
},
My problem here though, is that I must wait for this variable to update and then asign it to a new variable inside data() too, called query. But everytime I reference it as this.name I get an error because name is undefined. Here's my query I'm trying to submit
query: firebase.firestore().collection('feed').limit(3).where('author', '==', /*here goes name*/),
I must have this query variable in data() because then I got to pass it as a prop to a new component:
<post-card
v-bind:query="query"
></post-card>
Here's my data() too:
data() {
return {
doctorsCollection: firebase.firestore().collection('doctors'),
name: 'hello',
query: firebase.firestore().collection('feed').limit(3).where('author', '==', this.name),
speciality: '',
member_duration: '',
email: '',
phone: '',
age: '',
profilePicture: '',
dialog: false
}
},
I've just solved it by placing the query change inside created.
created: async function fetchDataFromFirebase() {
this.email = this.getCurrentUser().email
await this.doctorsCollection.doc(this.email).get().then(async (doc) => {
this.name = await doc.data().title + ' ' + await doc.data().firstName + ' ' + await doc.data().lastName
this.speciality = await doc.data().speciality
this.phone = await doc.data().phone
this.profilePicture = doc.data().img == null || doc.data().img === '' ? 'https://firebasestorage.googleapis.com/v0/b/healthy-wo.appspot.com/o/doctors%2FMantraHW-T-Coral-01.png?alt=media&token=2ae855cb-c96d-4b97-b813-c844f9e0e871':doc.data().img
// getCurrentAge will give the difference in years between today and the Date object you're passing
this.age = this.getCurrentAge(new Date((await doc.data().birthDate).toMillis())) + ' años'
// memberDate is a variable that holds the date this user was registered but in Date object format
let memberDate = new Date((await doc.data().subscriptionStart).toMillis())
this.member_duration = memberDate.getDate() + '/' + (memberDate.getMonth()+1<10 ? '0'+(memberDate.getMonth()+1):memberDate.getMonth()+1) + '/' + memberDate.getFullYear()
})
this.query = firebase.firestore().collection('feed').limit(3).where('author','==', this.name.toString())
},
data() {
return {
doctorsCollection: firebase.firestore().collection('doctors'),
name: 'hello',
query: 'null',
speciality: '',
member_duration: '',
email: '',
phone: '',
age: '',
profilePicture: '',
dialog: false
}
},
And also using a v-if statement inside my component. So it won't be rendered unless query is different from an initial string.
<post-card
v-if="query !== 'null'"
v-bind:query="query"
></post-card>

Lodash: Join values by given key

I am trying to search easy function on Lodash.js for joining values by given key or something...
Example:
const obj = {firstname : 'John', title: 'Mr.', lastname: 'Due'}
Expected results:
Mr. John Due
Any function like _.join() but better and I can do something like..
_.joinX(obj, ['title', 'firstname', 'lastname'], ' ')
Why not just...?
obj.title + ' ' + obj.firstname + ' ' + obj.lastname
Because sometimes my object is so long like... (And I will not give more variable)
obj.current.user.info.title + ' ' + obj.current.user.info.firstname + ' ' + obj.current.user.info.lastname
You can port the following to Lodash.
const joinByKeys = (obj = {}, props = [], separator = '') => {
// empty array.
let arr = [];
// push props to array
props.forEach(p => arr.push(obj[p]))
// return the joined array.
return arr.join(separator);
}
const obj = {firstname : 'John', title: 'Mr.', lastname: 'Due'}
console.log( joinByKeys(obj, ['title', 'firstname', 'lastname'], ' ') );
I think I got it:
const obj = {firstname : 'John', title: 'Mr.', lastname: 'Due'}
let name = _(obj).pick(['title', 'firstname', 'lastname']).values().join(' ')
console.log(name)
Not really special function as I expected but have to run tho Lodash's functions a bit

Categories

Resources