I have the following module class and to make it work similar to non module functional javascript, I have to call a function to bind all the class member functions to the correct this
scope and I have to explicitly add this.
when referencing class members.
Is there a way to remove these requirements so that module code looks exactly the same as functional code (see how it works in typescript in nodejs).
The only thing to pay attention to in the code examples is the addition of this.
and the requirement to call bindProperties()
function in the module class. If you don't call the bindProperties()
function the variables and the classes and the event handlers all lose scope. The this
in those cases could be anything. The content of the example code is not important.
Including javascript in an HTML page (notice no mention of this
in any of the code or in the event handler):
<script src="myscript.js"></script>
// myscript.js
"use strict"
var button = document.getElementById("button");
button.addEventListener("click", buttonClicked);
function buttonClicked(event) {
alert("Hello world");
}
The same thing in a module class is the following (notice the multiple uses of this.
and the necessary call to bind()
in the constructor):
<script src="myscript.js" type="module"></script>
// myscript.js
export App class {
button = null;
constructor() {
try {
this.bindProperties(App);
this.button = document.getElementById("button");
this.button.addEventListener("click", this.buttonClicked);
}
catch(error) {
this.log(error);
}
}
buttonClicked(event) {
alert("Hello world");
}
// this method is required to make the `this.` point to the class in all of the functions and event handlers
bindProperties(mainClass) {
var properties = Object.getOwnPropertyNames(mainClass.prototype);
for (var key in properties) {
var property = properties[key]
if (property!=="constructor") {
this[property] = this[property].bind(this);
}
}
}
}
What I'd like to know is if there is a setting to remove the need for needing to write this.
and to remove the need to call, bindProperties()
. Note the lack of this.
and the lack of bindProperties()
:
<script src="myscript.js" type="module" version="2"></script>
// myscript.js
export App class {
button = null;
constructor() {
try {
button = document.getElementById("button");
button.addEventListener("click", buttonClicked);
}
catch(error) {
console.log(error);
}
}
buttonClicked(event) {
alert("Hello world");
}
}
Basically, is there an option to remove the need for adding this
and an option to remove the need for calling bindProperties.
What am I talking about? Look at typescript/javascript in nodejs. You never need to use this.
, you don't need to call binding function on classes. The scope is always what you expect it to be.
But for client side javascript, I'm using typescript it is aware of the scope issue and by default it adds this.
to any class members with code complete. And it flags it if it doesn't have it.
This is confusing for Javascript newbies who might not understand why they need to bind the this
on class modules when they don't have to do it in non module scripts or in nodejs.
But maybe I'm missing something. I hope this makes sense.
Again, if you write code in a normal script included in a web page, you don't need to do any of these scope things that you have to do when using a module.
In other words, is there a setting to make modules code and behavior syntactically the same as non modules / nodejs code? The answer is probably no obviously but typescript has so many options maybe I missed it.
Update
In this linked post is this comment:
Changing myVariable to this.myVariable fixes the issue, but doing that for every variable clutters up my code quite a bit.
And once he starts building modules he will have the other issues I mention above.
globalVariable
be in the second example? If it is supposed to beclassVariable
, then this is not possible, asclassVariable
cannot be accessed directly in that manner. – Wayzgoosewith
:function C() {}
/C.prototype.foo = 42;
/C.prototype.bar = function() { with (this) { console.log(foo); } }
/new C().bar() // 42
.with
statements are forbidden in strict context (which ES6class
es enforce implicitly), so unless you are willing to use ES5 functions to do OOP... – WayzgooseMath
). – Wayzgooseclass
es for modularisation. Use ES modules, or plain functions. – Dramaticthis
context, regardless of the environment ... node.js versus browser/client side, module encapsulated code versus functions declared within a global scope ... it all does not make any difference. Please provide example code which proves me wrong. – AretinobuttonClicked
method which gets passed as an event-listener's callback-handler. In the very moment of being invoked by the internal listener'shandleEvent
method, thethis
context of cause is different than the one of e.g.appInstance.buttonClicked()
. Thus one either does bind explicitly or via an arrow function's lexical scope. – Aretinotype="module"
,import
&export
) withclass
es? Those are two separate things, you don't need to combine them. Which one do you want to use, and why? It's not even quite clear what you think is wrong with the original "non module functional javascript", it seems that is the most simple and straightforward code. The particular example you've shown does not benefit from anything that modules or classes have to offer imo. – Dramaticthis.
to every class variable. and i don't want to have to bind this on all event handler calls. other languages handle this somehow – Arenicolousthis.
to every class member and i don't want to have to bind this on all event handler calls. other languages handle this somehow. there might be a name for it. there might be a name for how javascript has different scopes compared to other languages. maybe it's different bc js is prototype based. but i'm asking if there is a name for this scoping behavior and if there is an option to change it. if not that's fine. – Arenicolousthis
in order to refer to the currently bound context. In addition, at instantiation/construction time, a constructor function might create enclosed scope as well. But scope and context are entirely different things ... – AretinobuttonClicked
is a property, so you have to access it like a property. Or you can go write e.g. Opal Ruby instead and compile Ruby to JavaScript, so you don't ever need to writethis
. To clean this up, instead ofthis.buttonClicked
, useevt => this.buttonClicked(evt)
orthis.buttonClicked.bind(this)
, and then you don't need ugly hacks likebindProperties
. – Binnsthis.
to every class member and i don't want to have to bind this on all event handler calls. other languages handle this somehow" - no. Very few languages mess up the distinction between scope variables and object properties/attributes. And for autobinding, see #41128019 and #20279984. But yes, JavaScript is not Ruby! – Dramatic@
glyph). It does not distinguish variables from method invocations. – Binnsthis.
in a node based typescript class... – Arenicolous