Function greet!(name)
{
this.name = name!;
this.superpowers! = {
hello!: function!()
{
console.log('hello there')
}
}
}
const flash = new Superhero('Flash')
Flash.superpowers.greet()
Everything with an explanation mark after the name is something I've chosen (e.g., greet!)
I'm trying to get acquainted with JS and this Enki app is a quick walkthrough/cheat sheet. This solution seems right to me (drag and drop words) but it's not correct. Please help, I've googled functions and naming conventions and can't see where my error is
Are you trying like this? See the below snippet
class Superhero{
constructor(name){
this.name = name
}
superPowers(){
return {
hello: () => {
console.log(this.name)
}
}
}
}
const flash = new Superhero("John Wick")
console.log(flash.superPowers().hello())
Related
I have an issue where my tests are not running due to the following type error:
TypeError: _ViewStore.default is not a constructor
The app itself runs fine and I am assuming that the test cannot get the JourneyStore variable as it is used in the setCurrentPageFromJourney method of the ViewStore class.
Does anyone know what might be causing this?
The view store class:
class ViewStore {
currentPage: Stage;
previousPageHistory: Stage[];
constructor() {
makeAutoObservable(this);
this.currentPage = PDP_VIEWS.DEVICE;
this.previousPageHistory = [];
}
set setCurrentPage(page: Stage) {
this.currentPage = page;
this.previousPageHistory.push(page);
this.previousPageHistory = [...new Set(this.previousPageHistory)]; // removes duplicates
}
hasVisitedPage(page: Stage): boolean {
return this.previousPageHistory.includes(page);
}
setCurrentPageFromJourney() {
const journeyState = JourneyStore.journeyParams.state; // test passes if JourneyStore is not used (but then the app breaks)
switch (journeyState) {
case `a`:
this.setCurrentPage = PDP_VIEWS.DEVICE;
break;
case `b`:
this.setCurrentPage = PDP_VIEWS.INSURANCE;
break;
}
}
}
export default ViewStore;
In another file, the view store (and others, including the journey store) is instantiated like this:
import ViewStoreClass from './ViewStore';
const ViewStore = new ViewStoreClass();
I think the app uses Mobx which I am unfamiliar with and do not know whether that would make any difference.
The test:
describe('ViewStore', () => {
let store = new ViewStore();
test('should pass', () => {
expect(true).toBe(true)
})
});
By the way, the JourneyStore is just another class, with lots of properties and methods - I would show it but it will be a lot of code, and I think that may be all you need to know about it.
Any help would be greatly appreciated, thank you.
Relative newbie to JS and node(though I don't think the fact that it's node matters, but just in case), but learning fast. Probably more detail in this question than needed to ask it, but I'm attempting to include in here some explanation of what I do and don't already understand, in case that's helpful context. I suspect there's something simple I'm missing here...
I have a class A with a bunch of (static, though I don't think that matters?) functions in it. They all do pretty specific things. I have another class B calling functions in A based on the desired function name and arguments being in variables in B.
I understand I could do something like this:
class A {
static doIt(theFunctionName, theArguments) {
if (theFunctionName == 'asdf') {
this.asdf(theArguments);
} else if (theFunctionName == 'qwer') {
this.qwer(theArguments);
} else if (theFunctionName == 'zxcv') {
this.zxcv(theArguments);
// } else if ( .. etc ...) {
// ... etc ...
} else {
//return some kind of error or whatever
}
}
static asdf(theArguments) {
//do stuff and return something
}
static qwer(theArguments) {
//do stuff and return something
}
static zxcv(theArguments) {
//do stuff and return something
}
}
class B {
constructor(...) {
this.theFunctionName = ...;
this.theArguments = [...];
}
myResult = A.doIt(this.theFunctionName, this.theArguments);
}
Further, I understand I can access properties of an object dynamically:
obj[myKey] = something;
or
myResult = obj[key]
But functions?
I believe I'm looking for some way to do the latter with functions not just properties - some way to do the functions stuff more dynamically without all the if ... else if ... ?
I understand functions are first class in JS, and can be passed around like objects. But I'm not sure that helps here since I'm not passing the functions themselves, I'm choosing a function to call based on its name and arguments in variables... right?
I've tried a couple of things attempting to use the principles from the properties examples with functions but not getting the desired results. I'm guessing either this really can't be done (without all the if... else if... ... or I'm missing something simple.
Any help greatly appreciated. Thanks!
Functions are first-class members in JavaScript. An object that has a property whose value is a string is not fundamentally that different from one with a property whose value is a function. Ordinary bracket notation works just fine with function properties and methods:
class A {
static doIt(theFunctionName, theArguments) {
const fn = this[theFunctionName];
if (fn) {
return fn(theArguments);
} else {
//return some kind of error or whatever
}
}
static asdf(theArguments) {
//do stuff and return something
}
static qwer(theArguments) {
//do stuff and return something
return 'quer ran';
}
static zxcv(theArguments) {
//do stuff and return something
}
}
class B {
constructor() {
this.theFunctionName = 'qwer';
this.theArguments = 'foobar';
console.log(A.doIt(this.theFunctionName, this.theArguments));
}
}
const b = new B();
That said, this design pattern looks a bit odd - A does not have any own-properties on instances, so it's somewhat weird for A to be a class; it'd make more sense to be a normal object.
const A = {
doIt(theFunctionName, theArguments) {
const fn = this[theFunctionName];
if (fn) {
return fn(theArguments);
} else {
//return some kind of error or whatever
}
},
asdf(theArguments) {
//do stuff and return something
},
qwer(theArguments) {
//do stuff and return something
return 'quer ran';
},
zxcv(theArguments) {
//do stuff and return something
}
}
class B {
constructor() {
this.theFunctionName = 'qwer';
this.theArguments = 'foobar';
console.log(A.doIt(this.theFunctionName, this.theArguments));
}
}
const b = new B();
I don't quite know how to phrase this so I'll just dive ahead and try to explain it as best as I can.
I don't quite know how to store class properties without using them, or something like that.
If we have a class of Message that contains a method called addMessage.
We want to use this method. inside of a class called Magic.
How exactly do we do this?
class Message {
constructor(messageContainer) {
this.message = messageContainer;
}
addMessage(msg) {
this.message.innerText = msg;
}
}
class Magic extends Message {
constructor(magic) {
super();
this.magic = magic;
}
something() {
this.addMessage('Some random message');
}
}
We do:
const message = new Message(document.getElementById('message-container'))
in the code but never use message anywhere.
Instead we use Magic like so:
const magic = new Magic(something)
and then:
element.addEventListener('click', () => magic.something())
This does not work, it does seem logical to why it doesn't, its because message never gets used, but how could we make use of the addMessage method inside of Magic though?
I've tried a few things but nothing seems to work except for doing document.getElementById inside of the super(), but that seems to me like it defeats the point of using classes if I can't call it somehow in the code and have it keep the reference to the message container...
Any ideas?
The Magic constructor needs to take a messageContainer parameter to pass along to the Message constructor.
class Magic extends Message {
constructor(messageContainer, magic) {
super(messageContainer);
this.magic = magic;
}
something() {
this.addMessage('Some random message');
}
}
const magic = new Magic(document.getElementById('message-container'), something)
If you have lots of parameters and don't want to have list them all when calling super(), use an object to hold them instead of using seperate parameters. Each class can use the object properties that pertain to it.
class Message {
constructor(options) {
this.message = options.messageContainer;
}
addMessage(msg) {
this.message.innerText = msg;
}
}
class Magic extends Message {
constructor(options) {
super(options);
this.magic = options.magic;
}
something() {
this.addMessage('Some random message');
}
}
magic = new Magic({
messageContainer: document.getElementById("message-container"),
magic: something
});
Instead of inheritance, your use case is composed(Behavioral design patterns). Combining 2 objects to work together. here is basic sample to solve this.
class MessageContainer {
constructor(messageContainer) {
this.message = messageContainer;
}
addMessage(msg) {
this.message.innerHTML = msg;
}
}
class Magic {
constructor(msgContainer) {
this.container = msgContainer;
}
something() {
this.container.addMessage("Some random message"+ new Date().getTime());
}
}
const container = new MessageContainer(
document.getElementById("message-container")
);
const magic = new Magic(container);
document.addEventListener("click", () => {
magic.something();
});
<div style="height: 100px; color: red;">
click here
<br/>
<span id="message-container"></span>
</div>
I have a template named exercise. Template exercise is subscribed to exactly one exercise (data) from db.
I am building touch typing app. The template exercise is part where user writes down prepared text.
This template will be quite complicated.
I needed some additional logic, so I created class ExerciseText.
The goal is: I need to share object exerciseText within template helpers and events of template exercise. I need that object exerciseTexthave some state during live time of template exercise.
I wrote my code with help of Sacha's article
It works, but is this a good pattern? Thank you for any ideas.
ExerciseText.js
"use strict";
export default class ExerciseText {
constructor(exercise) {
this.text = exercise.text;
}
get getText() {
return this.text.split('');
}
// many logic wow
}
exercise.js
"use strict";
import ExerciseText from '../../../imports/api/client/ExerciseText.js';
Template.exercise.helpers({
exercise: () => {
if (Template.instance().subscription.ready()) {
return Template.instance().exercise;
}
},
text: () => {
if (Template.instance().subscription.ready()) {
return Template.instance().exerciseText.getText;
}
}
});
Template.exercise.onCreated(()=> {
var instance = this;
instance.autorun(() => {
var params = Router.current().params;
var lessonUrl = params.lessonUrl;
var exerciseOrder = parseInt(params.rank);
instance.subscription = instance.subscribe('exercise', lessonUrl, exerciseOrder);
if (instance.subscription.ready()) {
var lesson = Lessons.findOne() || {};
if (lesson.hasOwnProperty('exercises')) {
// lesson has only one published exercise
// there si only one element in that array
instance.exercise = lesson.exercises[0];
instance.exerciseText = new ExerciseText(instance.exercise);
}
}
});
});
It's been a long time since I learned OOP and I'm new to JS, so things might look weird for more advanced users - sorry :)
function page(title) {
this.subPages = [];
this.title = title;
}
page.prototype.addToSubPages = function(subPage) {
this.subPages.push(subPage);
}
page.prototype.getSubPages = function() {
return this.subPages;
}
Now I create 2 objects:
startPage = new page("start");
somePage = new page("foo");
...and try to add somePage into the array in startPage:
startPage.addToSubPages(somePage);
Now this doesn't seem to work, although it should be correct, if I'm not mistaken.
console.log(startPage.getSubPages());
This shows me that something is in the array, but the object appears to be empty. What am I doing wrong?
Also: How would I access a certain element in that array? Like this: startPage.getSubPages()[0].getFoo();?
Edit: Holy Mackerel, Batman! This is more like my actual code: http://jsfiddle.net/pZHKS/2/
You're all right, the code I posted actually works. As soon as inheritance comes into play, it doesn't work anymore. Why, though? It should work exactly like the code above, right?
function page(title) {
this.title = title;
}
function subPage() {
this.contentPages = [];
}
subPage.prototype = new page;
There are two problems.
your not calling page in subPage.
your using Child.prototype = new Parent; that's wrong, use Object.create instead
So the fixed code would be.
function page(title) {
this.title = title;
}
function subPage(title) {
page.call(this, title);
this.contentPages = [];
}
subPage.prototype = Object.create(page.prototype);