Cannot understand the new class feature of ES2015 - javascript

I'm having a difficulty to understand
how the class feature works out.
Can you super simplify it to me the following snippet
with simple everyday words?
I really find it hard to grasp the whole thing.
That super function looks very weird, also.
Thank you in advance.
class Dessert {
constructor(calories = 250) {
this.calories = calories;
}
}
class IceCream extends Dessert {
constructor(flavor, calories, toppings = []) {
super(calories);
this.flavor = flavor;
this.toppings = toppings;
}
addTopping(topping) {
this.toppings.push(topping);
}
}

I think easiest to understand is just to create a new instance of IceCream:
var iceCream = new IceCream('vanilla');
console.log(iceCream) // IceCream {calories: 250, flavor: "vanilla", toppings: Array(0)}
As you see, you wasn't needed to pass calories value - super calls parent class and takes that value.
When you have a constructor function, and instantiate new instance constructor method being fired first, to collect properties as you describe in it.
Comment, please, if something is unclear. I would love to provide more info.

Related

Javascript: allow certain classes to change properties of another class

I have Student class. The student has a grade.
Teacher class can change the student's grade.
Other classes (i.e., parent class) cannot do that. I think I get the part about how to change another class's property (please correct me if I'm wrong), but how to make sure that only the Teacher class can change the grade?
class Student {
grade = 'A';
changeGrade(grade) {
this.grade = grade
return `the new grade is ${this.grade}`
}
}
class Teacher {
changeStudentGrade(student, grade) {
return student.changeGrade(grade)
}
}
JavaScript does not support this functionality. However, you can still add suitable logic to facilitate it by checking the class that is trying to changeGrade within the method as follows:
changeGrade(grade, classChangingGrade) {
if (classChangingGrade instanceof Teacher) {
this.grade = grade
return `the new grade is ${this.grade}`
}
}
Then this method should be invoked as below:
return student.changeGrade(grade, this);
Disclaimer
Other classes can get around this by creating a new Teacher instance and invoking changeGrade as follows:
student.changeGrade(grade, new Teacher());

Creating a class in JS OOP

Can You help with this thing that I need to figure out. I started learning Js with OOP but I am kind of stuck with this, where am I making a mistake. This is the assignment I have to figure out
Create a class Car with a property that holds a number of doors and one method that prints the number of doors to the console.
class Car {
constructor(doors){
this.doors=doors
console.log(doors)
}
}
you need to create a method in the Car class to print the number of doors and then you need to instantiate the class with a given number of door & then call that method on it.
class Car {
constructor(doors){
this.doors = doors;
}
print(){
console.log(this.doors);
}
}
const bmw = new Car(4);
bmw.print()
Hey 👋
Yeah no problem :)
class Car {
constructor(doors) {
this.doors = doors;
}
printDoors() {
console.log(this.doors);
}
}
In JS OOP you have to define your member variables within the constructor by using the this keyword.
To access your variables somewhere else in the class you also have to use `this.
The printDoor() function has to be defined at its own to call it later on like this:
const numberDoors = 4;
const myCar = new Car(numberDoors);
myCar.printDoors();
// expected output: 4

Make long path codes shorter in java

I am pretty new to programming so I am not sure what this is called but in Javascript, for example
arr[0].obj[0].getSomething();
can be shorten to
var o = arr[0].obj[0];
o.getSomething();
so that we do not have to repeat
arr[0].obj[0]
what is the equivalent of this in Java? I can't seem to find it.
Also tell me what should the title be, I am not sure whether my title is appropriate.
You do it just the same way:
If you have
House[] houses; // An array of houses
// initialize and fill the array
... and inside the House class you have a field doors:
public class House {
Door[] doors;
// Initialize the array in a constructor, add getter and setter methods
}
Then you can do either
Color doorColor = houses[0].doors[0].getColor();
or you store the door you want in a variable and then ask for its color:
Door door = houses[0].doors[0];
Color doorColor = door.getColor();
With the given snipped I can understand your java code would look like as below.
class A{
B obj[];
}
class B {
public void doSomething(){}
}
lets say you have array of A class object as as your code snippet says
arr[0].obj[0].getSomething();
in java it would be of class A like below
A arr[]
so the code would be
arr[0].obj[0].doSomething();
we can write it as
A firstA = arr[0];
B firstB = firstA.obj[0];
firstB.doSomething();
or
B firstB = arr[0].obj[0];
firstB.doSomething();

Javascript/Ramda: How to make the following code functional

Hi I have the following object structure,
const usersList = {
NFr9F4WbBxR4H5ajolbS6q0skPF2: {
name: "justin davidson",
uid: "NFr9F4WbBxR4H5ajolbS6q0skPF2"
},
asas9F4WbBxR4H5ajolbS6q0sasF2: {
name: "sawyer davidson",
uid: "asas9F4WbBxR4H5ajolbS6q0sasF2"
}
}
It has a user ID as key, and it's user object nested within. I want to store the inner user data. I've been using Ramda JS and have done so by doing the following,
let x = []
const y = R.keys(usersList).forEach((uid) => {
x.push(usersList[uid])
return x
})
which returns
[{"name":"justin davidson","uid":"NFr9F4WbBxR4H5ajolbS6q0skPF2"},
{"name":"sawyer davidson","uid":"asas9F4WbBxR4H5ajolbS6q0sasF2"}]
..however I'd like achieve the same in a purely functional way. What would be the best approach here? I'm guessing compose and map but I can't seem to work it out. Looking for a little direction.
Thanks
Just use map instead of forEach:
const x = R.keys(usersList).map((uid) => usersList[uid])
It looks like there's also a values method that does what you want:
const x = R.values(usersList)
There isn't always a function tucked away in some lib that does exactly what you want it to do. Showing how to do things on your own demonstrates that you don't have to feel "stuck" when you're faced with a problem and you can't find a magical function to solve it for you. Once you learn the function exists, sure, go ahead and replace your home-brew solution with the built-in. But until then, don't be afraid to write code and move on.
// ovalues :: (Object k:v) -> [v]
const ovalues = o =>
Array.from(Object.keys(o), k => o[k])
const usersList = {
NFr9F4WbBxR4H5ajolbS6q0skPF2: {
name: "justin davidson",
uid: "NFr9F4WbBxR4H5ajolbS6q0skPF2"
},
asas9F4WbBxR4H5ajolbS6q0sasF2: {
name: "sawyer davidson",
uid: "asas9F4WbBxR4H5ajolbS6q0sasF2"
}
}
console.log(ovalues(usersList))
So yep, R.values does exist in the Rambda library, but next time don't be afraid to try to solve it on your own. You have a powerful brain, now use it ^_^

Javascript Variable Printing

I have a background in C++ but have some questions with what I'm trying to do in Javascript. I needed to make a pseudo class since Javascript doesn't have them. I basically want to print something different based on what selection is chosen. I only defined two "fruits" in this example but what I would be doing would use a lot more. Any help would be greatly appreciated. I know there are some flaws in this like the select does not link in any way to the fruit function.
<!DOCTYPE html>
<html>
<script>
function select_fruit(name)
{
var fruit_name = name;
}
function fruit(name, color, amt)
{
this.name = name;
this.color = color;
this.amt = amt;
}
apple = new fruit("apple", "red", 5);
orange = new fruit("orange", "orange", 1);
document.getElementById("name").innerHTML = name;
document.getElementById("color").innerHTML = color;
document.getElementById("amt").innerHTML = amt;
</script>
<body>
<select name="pick_these" onchange="fruit(this.value)">
<option value="apple">Apple</option>
<option value="orange">Orange</option>
</select><br />
<p>I want *amt *color *fruit</p><!--This should say I want 5 red apple, if it's selected on the dropdown-->
</body>
</html>
First of all, you are missing the <head> tag. That aside, you need to move your document.getElementById..... lines to the select_fruit() function, and change the onchange event to call select_fruit instead. Here's how I'd do what you're attempting:
HTML:
<select id="fruitlist">
<option value="apple">Apple</option>
<option value="orange">Orange</option>
</select>
<p id="result"></p>
JS:
window.onload = function() { // or just `(function() {` if script is after above HTML
var fruits = {
"apple":{
"color":"red",
"amt":5
},
"orange":{
"color":"orange",
"amt":1
}
}, result = document.getElementById('result');
document.getElementById('fruitlist').onchange = function() {
var selection = this.options[this.selectedIndex].value;
result.innerHTML = "I want "+fruits[selection].amt+" "
+fruits[selection].color+" "+selection;
};
}; // or `})();` if you used `(function() {` at the start
I'm going to go ahead and agree with cdhowie's comment about 125%.
Attempting to use JS like Java/C#/C++/ActionScript/etc is going to work.
You'll be able to eke something out, and it's going to do something functional, once you hack your way around it for a while.
But that's really, really not the way the language should be used.
If you've got a technical understanding of other languages, Crockford's "JavaScript: the Good Parts" is a great way to hit the ground running.
If you have limited/no understanding of how languages are parsed, or you're really feeling lost inside of JavaScript, compared to your comfort-zone, then Crockford's book is like a bootcamp for people who want a solid starting-point for grasping the language, at a low-level (using the language as-is, with no libraries and minimal use of design-patterns).
I would say that Stoyan Stefanov's "JavaScript Patterns" is a fantastic next-step, as it does exactly what it says on the label, and it does a great job of it.
Anyway, you've got quite a few problems, here.
The first is that your script is asking for elements and their values before they even exist.
JS/the DOM are not pre-compiled.
For the most part, until you get into client/server communication, or you're defining functions and using them elsewhere, what you see is what you get, in the order you put them down.
In this case, you're asking for an element where el.id === "name".
If you look above this line in your code, you'll notice that no element above it has that id.
The soluution here would be to make sure that your script is below the intended target (or to wrap everything in functions, and call the functions below the <select> so you know that it exists).
This brings us to the second issue: your elements have no IDs.
If you have no IDs on them, grabbing those elements by ID isn't going to work.
<select id="my-select-box"></select>
<script>
var select = document.getElementById("my-select-box");
</script>
If you put them the other way around, it won't work.
If you're missing an .id attribute, it won't work.
As for "classes", don't think of it as defining hard-classes and then creating instances.
Sometimes, that's useful/necessary.
Other times, all you need to care about is instances.
What I mean is: in C++, think of all of the times you might have been tempted to create a full-blown class, when really a simple struct might have done.
And what about a struct where all you really need is a single instance?
Now imagine giving that struct methods, without needing to do any other work (headers, etc).
<select id="fruit-list">
<option value="apples">apple</option>
<option value="oranges">orange</option>
<option value="bananas">banana</options>
</select>
<p id="fruit-output"></p>
var Fruit = function (name, colour, starting_amount) {
var public_interface = {
name : name,
colour : colour,
amount : starting_amount
};
return public_interface;
};
var apples = Fruit("apple", "red", 4),
oranges = Fruit("orange", "orange", 2),
bananas = Fruit("banana", "yellow", 1);
var fruit_basket = {
selected : "",
output_el : null,
apples : apples,
oranges : oranges,
bananas : bananas,
add : function (fruit, num) {
this[fruit].amount += num;
},
remove : function (fruit, num) {
this[fruit].amount -= num;
},
print : function () {
var fruit = fruit_basket.selected,
el = fruit_basket.output_el,
message = "I want " + fruit.amount
+ " " + fruit.colour
+ " " + fruit.name;
if (fruit.amount !== 1) { message += "s" }
if (el.hasOwnProperty("textContent")) {
el.textContent = message;
} else {
el.innerHTML = message;
}
},
select : function (el) {
var index = el.selectedIndex,
fruit = el.options[index].value;
fruit_basket.selected = fruit_basket[fruit];
},
set_output : function (el) {
fruit_basket.output_el = el;
}
};
var select_box = document.getElementById("fruit-list"),
output_el = document.getElementById("fruit-output");
fruit_basket.set_output(output_el);
select_box.addEventListener("change", function () {
fruit_basket.select(this);
fruit_basket.print();
});
This isn't the answer, but consider how much more straightforward this is than a C++ or Java solution, where you'd have to build classes for all of the above.
If this were more advanced, perhaps you'd consider separating your data from your view and your control in more obviously-separated ways.
But again, that doesn't mean that you need huge inheritance hierarchies, or lots of classes which do relatively little.
It's a very straightforward language, which supports construction/initialization, but you can also make a "singleton" just by inventing an object on the spot.
I'd suggest putting that research into it, if you intend to use the language seriously.

Categories