unable to access meteor this when using ecmascript [duplicate] - scope

This question already has an answer here:
ES6 Arrow function is changing the scope of this in Meteor.publish [duplicate]
(1 answer)
Closed 7 years ago.
When using meteor with ecmascript's arrow notation, using 'this' to access the value described in the documentation always fails. For example:
Template.temp.onCreated(()=> {
this.var = new ReactiveVar("")
})
and then access it via:
Template.instance().var
always fail. This is consistant in almost any use of 'this' in meteor, client or server side.
When inspecting from the client, I can see that "this" is compiled into "_this" which always cause the code to fail.
the code is compiled into:
_this = this
Template.temp.onCreated(function() {
_this.var = new ReactiveVar("")
})
Any advice is appreciated.

This is because arrow functions are bound to the scope at the time they are created. In your case, at the time of creation the scope is global and your function's scope is, therefore, the global scope.
In conclusion, this behavior is the correct one by design.
You should not use the arrow functions when it is not appropriate. It is not just a "short-hand" to save typing a few characters.

Related

What is ?. symbol used for in java-script? [duplicate]

This question already has answers here:
Null-safe property access (and conditional assignment) in ES6/2015
(11 answers)
Question mark before dot in javascript / react [duplicate]
(1 answer)
Closed 1 year ago.
I'm learning reactjs with some tutorial and doesn't understand how ?. is work.
Is anyone help me to understand this with simple word.
if (message?.attachments?.length > 0 ) {
return ...
}
If you want more code please ask.
repeated question.
answer here
The optional chaining operator ?. permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain is valid. The ?. operator functions similarly to the . chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined. When used with function calls, it returns undefined if the given function does not exist.
This results in shorter and simpler expressions when accessing chained properties when the possibility exists that a reference may be missing. It can also be helpful while exploring the content of an object when there's no known guarantee as to which properties are required.

Are there any differences between using `forRoot` or `register` when creating a Dynamic Module in NestJS? [duplicate]

This question already has an answer here:
While creating a dynamic module in Nest.js should i use registerAsync or forRootAsync?
(1 answer)
Closed 3 years ago.
I am new to NestJS and I would like to create a Dynamic Module for the injection of a metrics reporter provider. The documentation for NestJS says the following about Dynamic Modules:
...by convention we should call it either forRoot() or register() [when creating a Dynamic Module]
Unfortunately, the documentation gives no clear guidance as to when you should implement register or forRoot or what the expectations in the implementation of the two functions should be. This leads me to believe that I could call the function cheeseburger and as long as it returns a DynamicModule.
What I like to do is use forRoot/forRootAsync for initial module configurations. From there if I need to be able to pass in new options for some services i like to use forFeature. This helps me keep in mind that the DyanmicModule is configured in the root of my application (usually AppModule) and can be used elsewhere in the application, either via forFeature() or by importing the expected module. Otherwise, you are absolutely right, you could call it cheeseburger and it would be just fine. No differences other than what others using the package might be expecting

Nodejs and implicit global variables?

I'm using some external libraries intended to be used in a browser and they set global variables implicitly like a='a' (without the var).
It seems like when I require certain scripts that do this, sometimes the variable will be accessible outside its scope just like in a browser, but for other scripts the global variable is not accessible outside its own script.
Anyone know how nodejs handles implicit global variables, and why I'm seeing somewhat random behavior? I found surprisingly little on the internet.
I can go into the scripts. write something like
if(typeof exports !== 'undefined' && this.exports !== exports){
var GLOBAL=global;
}
else{
var GLOBAL=window;
}
and then change all implicit references to GLOBAL.reference but these scripts are not my own and every time I want to get the latest version of them I would have to do this over again, which is clearly not desirable.
Using module.exports would be cleaner because then I don't have change all the references, but just add a section of the top of every file that exports the globals, but my original question about how node handles implicit globals is still relevant
I am not sure if this answer will help you, since it is hard to diagnose what is going on with your code, but maybe, some of this reasonings can help you diagnose the actual problem in your code.
The behavior in node is actually similar to that of the browser. If you would declare a variable without the var keyword the variable will be accesible through the global object.
//module foo.js
a = 'Obi-wan';
//module bar.js
require('./foo');
console.log(global.a); //yields Obi-wan
console.log(a); //yields Obi-wan
It is not clear why you say this behavior is not consistent in your code, but if you think about it, the use of global variables is precisely subject to this kind of problems since they are global and everyone could overwrite them at any time, causing as a result this unexpected conditions.
There is one aspect in which node is different from the browser though and that could be affecting the behavior that you see.
In the browser, if you do something like this directly in a JavaScript file:
console.log(this==window); //yields true
But if you do the same thing in a Node.js module:
console.log(this==global); //yields false
Basically, in the outer scope of a Node.js module the this reference points to the current module.exports object.
console.log(this==exports); //yield true
So, chances are that if you are putting data in the global scope (window) in the browser through the use of this, you may end up with a module scope in Node.js instead.
Interestingly, the code inside a function in Node.js behaves pretty much as in the browser, in terms of the use of the global scope.
(function what(){
console.log(this==global); //yields true
})();
This does not directly answer your question but it provides a solution since I don't think it is possible.
I love regexp. They are so powerful:
js = js.replace(/^(\t|\s{4})?(var\s)?(\w+)\s=/gm, function () {
if (arguments[1] || arguments[2]) return (arguments[1] || '') + (arguments[2] || '') + arguments[3] + ' =';
return 'exports.' + arguments[3] + ' =';
});*
JSFiddle here
How does it work? I will retrace my work:
/(\w+)\s=/g will take any var, return 'exports.' + arguments[1] + ' ='; will turn them into an export. Not very good.
/(var\s)?(\w+)\s=/g will take any var, but in the callback we examined first group (var\s). Is it undefined? Then we should export it, else nothing should happen. But what about scopes?
/^(\t|\s{4})?(var\s)?(\w+)\s=/gm now we use indent to determine the scope :)
You should be able to run this regex on your file. Be careful, you need it properly indented, and be aware that I might have forgotten some things.
Ah, the problem was that the global variable that was being declared globally in the browser wasn't being declared via a='a', but with var a='a'. In a browser if the var keyword is used not inside a function it will still declare a global variable. It only declares a local variable if the var keyword is inside a function. Node.js doesn't behave this way, and all var declarations are considered local.
Its ashame node.js does this, it makes it less compatible with browser scripts, for no real reason. (other than allowing people not to have to wrap all their scripts in a function).

Keep `this` on prototype's object [duplicate]

This question already has answers here:
Organize prototype javascript while perserving object reference and inheritance
(3 answers)
Closed 8 years ago.
I am trying to build a small javascript library for study purposes. I have an object inside a prototype that has some functions inside. I would like to access this (the one that has valueOf and stuff) from inside the functions, but this now brings me only the object parent to the functions.
My code (coffee):
HTMLElement.prototype.on =
click: (action) -> #valueOf().addEventListener('click', action, false)
# I'd like this to work,
# but `this` here refers to the `on` object
Is this possible? I know I'm kinda reinventing the wheel, but as I said, it's for study purposes, so that's the idea.
I am not 100% sure about the "this" the OP is referring to but I'll try to answer:
Let's first compile your coffee-script code to javascript:
HTMLElement.prototype.on =
click: (action) =>> #valueOf().addEventListener('click', action, false)
HTMLElement.prototype.on = {
click: function(action) {
return this.valueOf().addEventListener('click', action, false);
}
};
Ok, all right. In javascript the value of this in a function can be determined by many factors, one of which is a MemberExpression. When you call a function with a.b(), where a is an object, this inside the function b will be bound to a. In your case you are probably calling the function like that:
element.on.click(...);
The issue is that element.on is itself an object. The expression will evaluate to
(element.on).click(...);
and the value of this in the click function will be the object prototype.on, not element.
Basically, don't do it that way. It will be a pain to bind this to the HTMLElement instance. Put the function directly on the prototype. The only solution I can think of (terrible, shame on me) is:
element.on.click.bind(element)(...)
If I understand your problem correctly, the solution is the => Operator.
http://coffeescript.org/#fat-arrow

Directly calling a function bound to the exports object

I'm reading the cluster.js file of the cluster package and this part confuses me:
fs.readdirSync(__dirname + '/plugins').forEach(function(plugin){
plugin = plugin.replace('.js', '');
exports.__defineGetter__(plugin, function(){
return require('./plugins/' + plugin);
});
});
I know that you can bind objects or functions to the exports object to expose them to different files, but it seems that it is calling a function already bound to the object. However, I always thought you needed to require the file and access functions that way. What is going on here?
This is realization of lazy loading for plugins. Plugin will be loaded only after first access to module property with his name. __defineGetter__ is the 'syntax sugar' not presented in ECMAScript standard. It binds an object's property to a function to be called when that property is looked up.
If a module sets exports to a single function rather than an arbitrary object, then the result of require will be a function reference which can be called directly (note that a function is actually a type of object and as such can have properties, which can also be functions).
That's not what's going on here, though. At the time the code you've shown is executed, a function called __defineGetter__ has already been defined and attached to exports. Here it's simply being called as a method of exports (presumably because the author didn't feel the need to create a redundant local name for it).
i.e. somewhere along the line there's something like
exports.__defineGetter__ = function(propname, getter) {
...
}
Since it doesn't have a local name, the only way to call it is through exports.
Obviously the purpose of the code here is to allow you to call cluster.nameOfPlugin.method(...) without having to manually require each plugin, while not requiring all the possible plugins to be preloaded; instead only the ones you actually use get loaded.

Resources