I am currently learning JavaScript, and have a question about _variable name.
Firstly, what is the relationship between valuable name, and same valuable name with underscore? I am using this._title in getter and setter to get value from title, but I do not understand why _title can be used without declaring, and also when console this._title, it is able to show the value of title.
const movies = [];
const addMovieHandler = () => {
const title = document.getElementById('title').value;
const newMovie = {
info: {
set title(val) {
if(val.trim() === ''){
this._title = 'DEFAULT';
return;
}
this._title = val;
console.log(this)// shows the object of new movie
console.log(val)// show value of title
console.log(this._title)// also show value of title
},
get title() {
return this._title.toUpperCase();
}
}
};
newMovie.info.title = title;//setter
console.log(newMovie.info.title);//getter
movies.push(newMovie);
};
Thank you for your help!
Nagisa
Stepping back a bit, traditionally:
title = 'foo'; // assigns value 'foo' to title (set action)
console.log(title); // references title (get action)
You work directly with title, assigning a value to it directly, and when you reference it, js returns the value of it.
The concept of get and set methods is that you can add a proxy layer to the variable to write your own code to define what happens when you assign something to title (set) or reference it (get). This is most commonly used to add logic for default values or validate/scrub/format values.
So in your code, title and _title are two distinct variables that are not directly/intrinsically tied together, except by your own conventions set within title's set and get methods.
And within set and get, you do whatever you want. In this case, you are using an "internal" variable _title to hold the actual value. This can be named anything you want, but by convention, many people use the same variable name as the public one, but with a _ prefix. You don't even need to have one at all; it just depends on what your goal is.
Related
I am unsure of why I would exactly need to use a class here or perhaps a better way to say it is: I am not sure how a class is helpful as opposed to just forming objects on the fly.
export default class Car {
constructor(type="not specified", engine="V6") {
this.type = type;
this.engine = engine;
}
getType() {
return `the car type is ${this.type}`
}
}
main.js
import Car from Car.js;
let allCars = [];
function userSubmittedCarInfo() {
let typeValue = document.getQuerySelector('.input-type').value;
let engineValue = document.getQuerySelector('.input-engine').value;
// not sure the difference of just sending data as an object vs sending as class object?
//option 1 .... for object on the fly that I can post to server. Push it to list if I
// need a running list of all objects later on.
let obj = {
type: typeValue,
engineValue: engineValue,
}
allCars.push(obj);
//option 2... second option is create an instance of Car class
let obj = new Car(typeValue, engineValue)
fetch('url-i-am-posting-to', {
car: obj
})
}
Classes are generally useful when you want to tie together data with methods that operate on that data. Your Car here gives instances both properties on the instance (data) as well as a method that operates on the data (getType).
If you actually do want to call the getType method at certain points in the code, or if you add additional methods on the Car, having a class is quite a reasonable choice - you just have to pass in the data, and it'll return an object containing both the data and useful methods for that data.
But if you don't need methods - like in this example, it doesn't look like you're ever calling getType - then a class may well not provide any benefit, and could be considered to only be adding confusing overhead, and using an object literal would make good sense instead (arguably, even more sense).
I am trying to call the relevent data from Firebase based on the paramater in the URL.
For example:
var userId = 'EqBOy1RVZacBCaNlzbG9NDHrXl23'
//sets the variable to the exercise name in the url
var exerciseName = this.$route.params.exercise_name //'dumbbell_extension'for example
db.collection('track').doc(userId).get().then((doc) => {
if (doc.exists) {
this.exerciseData = doc.data().exerciseName //Returns 'undefined'
}
})
Here is a picture of the database:
Firebase Document Image
This returns undefined despite of the data existing in Firebase and everything else working as intended. I presume this is because it is actually searching for a field called exerciseName instead of the variable exerciseName.
The data() method of a DocumentSnapshot "retrieves all fields in the document as an Object".
You should therefore use the square bracket notation, which allows you to access the Object properties by name, as follows:
var userId = 'EqBOy1RVZacBCaNlzbG9NDHrXl23'
//sets the variable to the exercise name in the url
var exerciseName = this.$route.params.exercise_name //'dumbbell_extension'for example
db.collection('track').doc(userId).get().then((doc) => {
if (doc.exists) {
this.exerciseData = doc.data()[exerciseName]
}
})
You may also be interested by this answer https://stackoverflow.com/a/4968460/7015400, which gives more details about the square bracket notation.
Your code is looking for a field called "exerciseName" in the document, but the document has no such field. The only field in your document, as shown in the screenshot, is called "dumbbell_extension", and we can't see what it contains (it could be a list or map).
Since we don't know what your code is expecting to do, there's no much else to be said. Your code needs to use the names of the fields that are present in the document, or check to see if they actually exist before using them.
I have imported a few classes in Adonis
const User = use('App/Models/User')
const Orders = use('App/Models/Orders')
I want to be able to access one of the above classes dynamically. By that I mean a variable will hold the class I want to access. The variable will be populated by via an API call from the user.
let className = 'Orders'
How to I use the className variable to access the Orders class.
I have tried
[className].query().where('orderNumber','123').fetch()
However that does not seem to work.
Create a name -> class map:
const classes = {
__proto__: null, // to avoid people being able to pass something like `toString`
Users,
Orders,
};
// or if you don't want to use __proto__
const classes = Object.assign(
Object.create(null),
{Users, Orders}
);
and access the right class with classes[className]. Of course verify whether the class exists or not.
I have tried
[className].query().where('orderNumber','123').fetch()
However that does not seem to work.
In this context, [...] denotes an array literal, so [className] just creates an array containing className (which is a string in your example) as only element.
Avoid converting the variable to a string at all. Just use:
let className = Orders;
className.query().where('orderNumber','123').fetch()
If the class is being instantiated by an API call, use a simple switch statement:
let class;
switch (apiCall.name) {
case 'orders':
class = Orders;
break;
case 'users':
class = Users;
break;
default:
throw 'Invalid API Call';
}
class.query().where('orderNumber','123').fetch()
Easiest would be to eval(className).query().where('orderNumber','123').fetch(), but if you want to check the values existence as an actual class, you probably should implement a switch or if-else-if to check and assign className and call only if it is actually present.
so i'm trying my hands on writing my very first library module using pure javascript except that i just hit a snag and need a little bit of help.
I'm using Revealing module pattern because of its neatness. In my module i have my default params in an object like this.
var defaults = {
name : 'John Doe',
age : 'Unspecified,
height : '5feet'
};
And this works splendid, but i have an init function where a user can pass an object with these keys. e.g
Module.init({
name : 'james',
age : 12
});
Now in my code, i try to write a function that returns the values of each of these keys comparing the default values and the initialized one. If the key/value exists initialized, it should return it else use default. I know what i want, but don't know how to check the objects keys just yet.
function getValues (defaultObject, initObject){
//scans the keys and returns the values
}
So in code i can do stuff like
var options = getValues(defaultObject, initObject);
var name = options.name;
This means that name will either be james if specified or john doe if not. Also for height since i didn't set a value, i get the default too
Thanks in advance guys.
What you need to do to compare both objects keys, and if the new object has a key, then replace the value in the old one. Here's an example:
function getValues(defaultObject, initObject) {
for (var key in initObject) {
if (initObject.hasOwnProperty(key)) {
defaultObject[key] = initObject[key];
}
}
return defaults;
}
I hope this help you.
See my answer in another thread how to
better define function optional default params : https://stackoverflow.com/a/52082835/1422407
It may help you to redefine function signature, and as result less useless logic in function itself.
Background
While working on an ongoing learning project, I noticed that I require a writeable computed function to solve a problem I'm facing. Here's the skinny: I'm trying to 1) drop a user-specified number of assignments scores 2) of a user specified type from a gradebook.
The user inputs the value above, then click a button, dropLowestScores. The code then adds the lowest scores to an array called 'lowest', which exists on each student object.
Then, observable means on each student are updated based on new values, dropping the lowest ones.
Problem
My problem comes to life when I try to drop. I'm not confident that my writeable computed is structured correctly, but I'm not sure what's wrong either. I noticed that that properties 'n' and workType are correctly given in my read function, but in my write, they are not as desired. In read, for example, workType returns default value, homework, but in my write function, it returns [object Object].
Responses that can clarify what my problem is and give me a strategy for correctly scripting a writeable computed would be appreciated.
Relevant JS and HTML snippets follow.
JSBin: Full Project
JS
this.dropLowestScores = ko.computed({
// read the parameters necessary to write values to property 'lowest'
read: function() {
// user sets value of 'n' in the page via ko 'options'
var n = _this.n().n;
// user selects 'workType' from list of ko options
var workType = _this.workType().workType;
console.log("workType:" + workType);
return n,workType;
},
// now use current parameter values to set new values to 'lowest' arrays
write: function(n,workType) {
//this.n = n;
//this.workType = workType;
// 'lowest' exists as a property for each student,
// ergo, I loop through each student
ko.utils.arrayForEach(_this.students(), function(student){
var i = _this.students.indexOf(student);
console.log("_this.assignments: " + _this.assignments()[i].workType().workType);
console.log("this.workType: " + this.workType);
console.log(_this.assignments()[i].workType().workType == this.workType);
// if the current assignment is the same as the user-specified assignment,
//add the score for that assignment to array 'tmp'; then set lowest = tmp
if(_this.assignments()[i].workType().workType == this.workType){
var tmp = student.scores().sort(_this.comparator).slice(0,this.n);
console.log(tmp.length);
student.lowest(tmp);
}
});
}
});
HTML
<button data-bind="click: dropLowestScores">Drop Lowest Scores</button>
Currently, I just have the above function bound to a butten. Ideally, this is how I'd leave it. Other properties referenced, such as n, workType, and mean are input in a table.
I feel silly now, but it turns out I was on the right track; indeed, the solution was trivially simple. In the read function, I just needed to define properties in the following way:this.variable = ... as opposed to var variable = ....
this.dropLowestScores = ko.computed({
// read the parameters necessary to write values to property 'lowest'
read: function() {
// user sets value of 'n' in the page via ko 'options'
this.n = _this.n().n;
// user selects 'workType' from list of ko options
this.workType = _this.workType().workType;
console.log("workType:" + workType);
return n,workType;
},
...