I want to dynamically create constructors. Thats why I have a factory function which gives back a constructor function. However, when I try to call super() in this function, the parser complains that its unexpected there.
function makeConstructor (someInput) {
return function () {
super() // SyntaxError: 'super' keyword unexpected here
// and other stuff depending on someInput
}
}
class MyClass {
constructor: makeConstructor(foobar)
}
As you can see, when this code would execute, the super call would make totally sense because it is a constructor.
So the question is: How can I ship around this issues? Are there other possibilities to create constructorfunctions like this?
Related
I have please encountered the following example in a book of a declaration of a class inside a function argument, even though I have searched thoroughly online, could not find an explanation, what it does, what is declared, what is passed into the function, and when should I use it if at all (perhaps its a bad practice ?).
Thank you for your help and guidance !
function f(parameter1) {
console.log(parameter1);
}
class ClassA {
}
f(class extends ClassA {
render() {
}
});
In javascript, class is just a syntax sugar for function, and just like function it's a first class value, which can be assigned, passed around etc.
let a = class {
foo() {
console.log('hey')
}
};
new a().foo()
//
function x(klass) {
new klass().bar()
}
x(class {
bar() {
console.log(2)
}
})
This is defining an anonymous class (in Java terminology... not sure if that is the correct name for JS). This example is pretty nonsensical. I could see it being used if the function f was accepting a class definition and then instantiated an object using it and proceeded to call methods on the object and perhaps return it. So it could be used in a general factory function.
I am having tough time figuring out when should we preferably use this keyword and when shouldn't we use it..
For example, I was earlier doing something like this.
let socket;
class something extends Component {
componentDidMount() {
socket = openSocket('https://coincap.io');
}
componentDidUpdate() {
socket.on('trades', (tradeMsg) => {
}
componentWillUnmount() {
this.socket.disconnect();
}
then someone re-structured my code did something like
class something extends Component {
componentDidMount() {
this.socket = openSocket('https://coincap.io');
}
componentDidUpdate() {
this.socket.on('trades', (tradeMsg) => {
}
componentWillUnmount() {
this.socket.disconnect();
}
[Question:] While, Both the code works and do the job, I am perplexed between understanding which methods should we use and why did he used this keyword?
You are dealing with ES6, which takes out a lot of ambiguity pertaining to the this keyword in the language.
Quite simply, this means (in the more traditional sense) the current scope; however, in JavaScript, this means the object calling the function as opposed to the current scope.
As mentioned previously, ES6 takes out a lot of complexity regarding variable hoisting and the likes.
Coming to your question, the reason it was refactored to this.something was because when your class is called (now, remember, JavaScript follows prototypal inheritance and is a first-class language; meaning that function prototypes are the class bases and functions can be passed as parameters) it will act like a function and the this keyword will refer to the object or the context where it was called.
If we have the following bit of code:
let foo = 'bar';
const fn = () => { console.log( this.foo ); }
fn();
The execution context would be window and the foo variable would be window.foo; hence, this.foo would translate to window.foo.
Similarly, your code will be transpiled something like:
var socket = new Socket();
function className() {}
className.prototype.someFunction = function() {
console.log( socket );
}
Here, the this keyword would make sure that the current context is used instead of local variables which you might use within your function.
I hope this makes it clear. Here is a great article to understand the this keyword! :)
The problem isn't the difference between this and a variable per se. It's that this refers to class instance and allows to have multiple class instances and thus multiple socket instances, while socket variable refers to specific socket instance and will be overridden in subsequent component instances.
The component will malfunction if there's more than one component instance at time, because socket variable refers to latest openSocket('https://coincap.io') result.
Also, this
let socket;
class something extends Component {
componentDidMount() {
socket = openSocket('https://coincap.io');
}
componentDidUpdate() {
socket.on('trades', (tradeMsg) => {
}
componentWillUnmount() {
this.socket.disconnect();
}
will result in error on component unmount because there's no this.socket.
I have a function in a component that calls another function and both have the same name.
It works, both of the functions run
I would like to know why does it work (see my assumption below)?
A followup question, what if i want to call the external function recursively should i use this.myMethod()?
Is this pattern safe to use?
Example:
myMethod(){
const {myMethod} = this.props;
if(typeof myMethod == 'function'){ // i was sure this will check the external myMethod func
myMethod(); // i was sure it will call the external myMethod func.
}
// what if i want to call to the external "myMethod" func (recursively)?
}
I assume that the engine is searching for a function named myMethod inside the body of external myMethod (lexical scope?) and it finds it.
can anyone confirm this assumption?
EDIT
Just to make my question more clear about how common and safe this pattern is.
Let's say i have a component of Item and it has an onTouch prop of PropTypes.func, i would like to run some internal logic inside my own function and then run the function that received via the props as a callback or something similar.
Should i bother finding a new name to my internal function like onInternalTouch or is it safe to stick with the same name onTouch?
onTouch(){ // is this common practice?
const {onTouch} = this.props;
// ... internal component logic
onTouch();
}
onInternalTouch(){ // or should i bother finding a new name?
const {onTouch} = this.props;
// ... internal component logic
onTouch();
}
Please note that component myMethod method is defined as object (class) method so to call it from any component method you have to use this.myMethod(). There's no possibility that calling myMethod() (without this.) inside any component method will call component method with the same name. If you didn't define myMethod variable inside the method and tried to call it you'd get an error telling that myMethod is not defined. So such code will give you mentioned error:
myMethod(){
myMethod();
}
When you call a function JS firstly try to find such function defined in closest scope (in your case inside component myMehod method body), if there's no such function JS moves to next (parent) scope (in your case it'd be the same scope in which react component is defined) and tries to find it again and so on.. But it's imporant that component methods are not defined in any of those scopes but are defined as class methods so you have to use this.myMethod to tell JS that you mean method defined on 'this' object. Generally to call any object method you have to use method name associated with an object.
Situation would be different if it wasn't component methods but normal functions. Consider such code:
//here is outer scope
function myMethod() {
//here is inner scope
myMethod(); // this will call function defined in outer scope
}
myMethod();
it would give you 'too much recursion' error - there is no myMethod function defined in inner scope so JS uses function defined in outer scope.
If you now override outer function with inner variable with the same name there would be no errors:
//here is outer scope
function myMethod() {
//here is inner scope
var myMethod = function() {
console.log(12);
}
myMethod();
}
myMethod();
In above code variable defined in inner scope overrides function defined in outer scope so JS finds myMethod in inner scope and even doesn't try to search for myMethod in outer scope.
Back to you question - yes, if you want to call the external function recursively you have to use this.myMethod().
Question edit update:
As for your question regarding naming practice both options will work. It's just a matter of code readability and good practices. I'd personally use different meaningful names. In your example I'd use e.g. handleTouch for method name and touchCallback for prop name. Generally it's more difficult to understand code using the same names for different functions - you have to pay more attention to grasp what function does and where it comes from (is it component method or function passed as prop?).
Generally it's easy to get confused if you use the same names especially if someone else reads your code. Of course it's totally ok if two or more components have method with the same name if they do similar job but if one function calls another function IMO they should have different names because they have different purpose which should be reflected in their names.
Let's say I have a logging class called Logger.
let log = new Logger(...);
Is it possible to specify a magic method in that class to be executed when the class instance is invoked as function? For example
log(...)
In php implementing the __invoke() magic method of a class achieves the same thing.
function Logger() {
return function log(arg1, arg2) {
//#TODO: use the function's args
// or the arguments property to
// generate the log
console.log(log.arguments);
}
}
logger = new Logger();
logger('boom', 123, 'yolo');
This solution should to the trick you are looking for. How optimal it is or better ways of setting this up will probably be found in the comments below.
Newbie to classes in javascript and can't solve this problem. Actually, anothermethod can return a callback to constructor and then I can can call onemethod from there, but maybe there's an easier way?
function sample() {} //constructor
sample.prototype = {
onemethod: function () {},
anothermethod: function () {
onemethod(); //Doesn't work
this.onemethod(); //Still the same
}
}
For it to work, you need to use it correctly. A constructor needs to be call via new.
var s = new sample();
s.anothermethod();
// identical to
sample.anothermethod.apply(s);
This way, this will represent s (and this the outer context, usually window).