setTimeout & "this" keyword in nodejs - node.js

const person = {
talk() {
setTimeout(function () {
console.log(this);
}, 1000);
},
};
person.talk();
I know when you call a stand-alone function in javascript, "this" will refer to the global object (i.e., the window object in browser, or the global object in nodejs).
Since a callback function is a stand-alone function, I expect it will print window/global in the above example.
However, when I test it in browser, it did return the window object.
But when I run it in node, it returns a Timeout object rather than the global object. What is the reason behind it?

setTimeout() is not actually part of the Javascript standard - it is supplied by the host environment.
In the nodejs implementation, a timer is an actual object and nodejs calls the timer callback by calling a method on that object like this:
timer._onTimeout();
where this is set in the contructor of the object like this:
this._onTimeout = callback;
to the timer callback. Thus, this will be the timer object (due to the method call). You can examine the nodejs timer object source yourself here.
One of the reasons for nodejs to turn a timer ID into an object is that it also has other methods such as .ref() and .unref() which are cleaner to implement and expose to the programmer if the timer handle is an actual object rather than adding more functions to the global namespace.
The browser has a different implementation that calls the callback as a normal function. And, in Javascript (when not in strict mode) calling a normal function sets this to the global object in the function.
As I said in the comments, you should NOT rely on any value of this that is not explicitly documented to be what you want or controlled by the way you have called things. To do so is just playing roulette.
If you want to explicitly reference the global object, then I'd suggest you just specifically refer to the global object as window.x or global.x depending upon your environment.

The answer to your question can be found here:
Different behaviour of setTimeout in nodejs and Chrome.
In short, Node's setTimeout is a different function than a browser's setTimeout, despite having similar functionality and identical name. I do not know the underlying reason they were created to have different this references, but they do.

The reason behind this is that this binding is determined based on where it was called not where it is declared.
There are four rules according to You don't Know JS books
Default Binding
example
let world = "hello world"
function hello() {
console.log(this.world)
console.log(this)
}
hello() // prints hello world and global object
//the call site is on the global environment
Implicit Binding
example
let object1 = {
world: "I am being called from object1 site ",
hello: hello
}
let object2 = {
world: "I am in 2",
object1: object1
}
object2.object1.hello() //will print " I am being called from object1 site because of the taking the object that is closest level to the function and that is objec1"
obj.hello() // print "I am being called from object1 site and object1 properties
Explicit Binding
This occurs when you are 'explicit' about the object you want this to refer to and in this case you use call, apply and bind (which is more stronger in binding this to expected object)
Example
hello.call(object1) in this case this will refer to object1. In an event where call or apply does not work you can use bind to make a hard bind .That is why you would see this pattern a lot
Let say you want to refer to the person object
const person = {
talk() {
setTimeout(
function () {
console.log(this);
}.bind(this),
1000
);
},
};
person.talk(); // `this` will refer to the person object
Let say you want to refer to global object in Node
let globalObject = globalThis;
const person = {
talk() {
setTimeout(
function () {
console.log(this);
}.bind(globalObject),
1000
);
},
};
person.talk(); // this will refer to global object
New Binding: this is using keyword new to create an object
Example let b = new life()
To determine this in code you have to know how it was used in the call site and they take precedence over in this order: new binding > explicit binding > implicit binding > default binding

Related

What should I do to understanding this case? (nodejs) [duplicate]

I have a JavaScript file which is loaded by require.
// loaded by require()
var a = this; // "this" is an empty object
this.anObject = {name:"An object"};
var aFunction = function() {
var innerThis = this; // "this" is node global object
};
aFunction();
(function(anyParameter){
console.log(anyParameter.anObject);
})(
this // "this" is same having anObject. Not "global"
);
My question is: this in var a = this; is an empty object whereas this statements in functions are shadows of node.js global object. I know this keyword is different in functions but I could not understand why first this is not equal to global and this in functions equals to global.
How does node.js inject global to this in function scopes, and why it does not inject it to the module scope?
Here's a few fundamental facts you must understand to clarify the situation:
In the top-level code in a Node module, this is equivalent to module.exports. That's the empty object you see.
When you use this inside of a function, the value of this is determined anew before each and every execution of the function, and its value is determined by how the function is executed. This means that two invocations of the exact same function object could have different this values if the invocation mechanisms are different (e.g. aFunction() vs. aFunction.call(newThis) vs. emitter.addEventListener("someEvent", aFunction);, etc.) In your case, aFunction() in non-strict mode runs the function with this set to the global object.
When JavaScript files are required as Node modules, the Node engine runs the module code inside of a wrapper function. That module-wrapping function is invoked with a this set to module.exports. (Recall, above, a function may be run with an abitrary this value.)
Thus, you get different this values because each this resides inside a different function: the first is inside of the Node-created module-wrapper function and the second is inside of aFunction.
To understand this, you need to understand that Node.js actually wraps your module code in to a function, like this
(function (exports, require, module, __filename, __dirname) {
var test = function(){
console.log('From test: ' + this);
};
console.log(this);
test();
});
Detailed explanation can be found in this answer.
Now, this wrapped function is actually invoked like this
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
So, this, at the module level, is actually the exports object.
You can confirm that like this
console.log(this, this === module.exports);
// {} true
Summary:
In Javascript the value of this is determined when a function is called. Not when a function is created. In nodeJS in the outermost scope of a module the value of this is the current module.exports object. When a function is called as a property of an object the value of this changes to the object it was called. You can remember this simply by the left-of-the-dot rule:
When a function is called you can determine the value of this by looking at the place of the function invocation. The object left of the dot is the value of this. If there is no object left of the dot the value of this is the module.exports object (window in browsers).
caveats:
This rule does not apply for es2015 arrow function which don't have their own binding of this.
The functions call, apply, and bind can bend the rules regarding the this value.
Example (NodeJS):
console.log(this); // {} , this === module.exports which is an empty object for now
module.exports.foo = 5;
console.log(this); // { foo:5 }
let obj = {
func1: function () { console.log(this); },
func2: () => { console.log(this); }
}
obj.func1(); // obj is left of the dot, so this is obj
obj.func2(); // arrow function don't have their own this
// binding, so this is module.exports, which is{ foo:5 }
Output:
It's because the default global object in a Node.js module is the exports object, and you are calling test() which doesn't specify this. In traditional JS, this points to the global object, with use strict, this will be null.
this can point to anything, it just depends on how you call it.
test(): Uses the global object (exports) as this, unless in strict mode, where this will be null;
test.call({}) or test.apply({}): You are specifying what to use as this (the first parameter)
var obj = {testRef: test}; obj.testRef(): this is set to the left of the ., that is, obj
Countering thefourtheye's answer
It is true that this in the top level of the module is exports, but that doesn't necessarily mean that this inside test() will also point to same thing as where it was called from.
Attempting to prove that this and the global object both point to exports
myGLobal = 5;
this.myGlobal; // 5

Check if a function exists inside another function in nodejs

Propose the following situation:
function functionExists(functionName) {
if (typeof window[functionName] == 'function') console.log("It's a function");
}
What would be an equivalent function in nodejs for functionExists where there is no global window variable?
CONCRETE SITUATION:
My concrete situation uses webpack instead of nodejs, but basically the problem is the same. I could use window here, but it would be too complicated to implement everything cleanly, and it isn't advised by webpack to mitigate things out to the window global variable.
Basically, I have a PHP backend, which generates a html <form> adding some options to it via a data attribute. When the page is loaded, my javascript initializes this <form> and gives it a bunch of functionalities (like validation for example). Another thing javascript does with this form, is that it parses the data attribute of it, and instead of the normal page reload submit, it changes the form so it is being submited over an ajax request to the server.
When this submit happens, it is set up, that the button and the whole form gets disabled, until my Ajax script sends back a response. How this is done, is that I have a Project_Form class, which when it is initialized, attaches itself to the jQuery submit event, stops the basic submit event, and runs an inner function which sends an ajax request to an api method. The ajax request is set up, that when a response is received, the same instantiated class will receive this response, so I can continue working with it.
When the form receives the response, it must do something with it. In the most basic situation, it must show a success message to the user, but there are some more complex situation, where for example, it has to make a page redirect (for example a login form). Right now, it is set up, that as a default, it will show a message, but when I define this form in PHP, I have the option to "hijack" this default behaviour, and instead of it, send the ajax response to a custom function, which will resolve the situation specifically.
When I am rendering the form in PHP, I already know where the form should send a success response (to which javascript function), but I can only provide this information to javascript, via a string. So my Project_Form class, should fetch this string, and should try to fetch a function from it which it will use. This is where my problem is coming from.
Unless you specifically KNOW that this is a global function (which is almost never the case in nodejs), functions by default in nodejs are scoped to the module and there is NO way to look them up by string name like you did with the window object in the browser, just like there is no way to look up local variables by name inside a function in Javascript.
In general, don't pass functions by string name. Or, if you have to, then you need to create a lookup table that you can check the function name against.
I'd suggest you explain the real problem you're trying to solve here because passing the function by string name is not how you would generally want to do things.
There is a bit of a hack using eval() that can see if a string represents a function name that is in scope:
// Warning, you must know that the argument f (if it is a string) does not
// contain harmful Javascript code because it will be used with eval()
function isFunction(f) {
// if already a function reference
if (typeof f === "function") {
return true;
// see if string represents a function name somewhere in scope
} else if (typeof f === "string") {
try {
return eval(`typeof ${f} === "function"`);
} catch(e) {
return false;
}
} else {
return false;
}
}
Note: This tests to see if the function is in the scope of the isFunction() function. If you want to test if it's in your current scope, then you need to do the:
eval(`typeof ${f} === "function"`)
inline in your current scope so it runs in the scope you want to do the lookup from.
To ever consider using this, you will HAVE to know that the source of your string is safe and cannot contain harmful code. But, as I said earlier, it's better to design your program differently so you aren't referring to functions by their string name.
And, here's a runnable snippet that shows it in action (also works in a node.js module):
function test() {
console.log("in test");
}
function isFunction(f) {
// if already a function reference
if (typeof f === "function") {
return true;
// see if string represents a function name somewhere in scope
} else if (typeof f === "string") {
try {
return eval(`typeof ${f} === "function"`);
} catch(e) {
return false;
}
} else {
return false;
}
}
console.log(isFunction("test")); // true
console.log(isFunction(test)); // true
console.log(isFunction("notAFunction")); // false
More added after question edit
If you only have the function name as a string and the function that it points to is not a property of some known object, then the only way I know of to turn that string into a function reference is with eval().
You could directly execute it with eval() such as eval(functionName + "()") or you could get a reference to the function with eval("let fn = " + functionName) and then use the newly defined fn variable to call the function.
If you control the various functions that could be referenced (because they're your Javascript), then you can make all those functions be a property of a known object in your Javsacript:
const functionDispatcher = {
function1,
function2,
function3,
function4
}
Then, instead of using eval(), you can reference them off the functionDispatcher object like you would have referenced before with window (except this isn't a global) as in:
functionDispatcher[someFunctionName]();
This would be a preferred option over using eval() since there is less risk of insertion of random code via an unsafe string.
In node.js you can achieve this like:
function functionExists(functionName) {
if(functionName && typeof functionName === "function")
console.log("It is a function");
}
Hope this works for you.

typescript and Nodejs this in controller returning undefined [duplicate]

I have a constructor function which registers an event handler:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
However, I'm not able to access the data property of the created object inside the callback. It looks like this does not refer to the object that was created, but to another one.
I also tried to use an object method instead of an anonymous function:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
but it exhibits the same problems.
How can I access the correct object?
What you should know about this
this (aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scopes like other variables (except for arrow functions, see below). Here are some examples:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
To learn more about this, have a look at the MDN documentation.
How to refer to the correct this
Use arrow functions
ECMAScript 6 introduced arrow functions, which can be thought of as lambda functions. They don't have their own this binding. Instead, this is looked up in scope just like a normal variable. That means you don't have to call .bind. That's not the only special behavior they have, please refer to the MDN documentation for more information.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Don't use this
You actually don't want to access this in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self and that.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Since self is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this value of the callback itself.
Explicitly set this of the callback - part 1
It might look like you have no control over the value of this because its value is set automatically, but that is actually not the case.
Every function has the method .bind [docs], which returns a new function with this bound to a value. The function has exactly the same behavior as the one you called .bind on, only that this was set by you. No matter how or when that function is called, this will always refer to the passed value.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
In this case, we are binding the callback's this to the value of MyConstructor's this.
Note: When a binding context for jQuery, use jQuery.proxy [docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.
Set this of the callback - part 2
Some functions/methods which accept callbacks also accept a value to which the callback's this should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map [docs] is such a method. Its signature is:
array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this should refer to. Here is a contrived example:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Note: Whether or not you can pass a value for this is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax method [docs] describes an option called context:
This object will be made the context of all Ajax-related callbacks.
Common problem: Using object methods as callbacks/event handlers
Another common manifestation of this problem is when an object method is used as callback/event handler. Functions are first-class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.
Consider the following example:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
The function this.method is assigned as click event handler, but if the document.body is clicked, the value logged will be undefined, because inside the event handler, this refers to the document.body, not the instance of Foo.
As already mentioned at the beginning, what this refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
The solution is the same as mentioned above: If available, use .bind to explicitly bind this to a specific value
document.body.onclick = this.method.bind(this);
or explicitly call the function as a "method" of the object, by using an anonymous function as callback / event handler and assign the object (this) to another variable:
var self = this;
document.body.onclick = function() {
self.method();
};
or use an arrow function:
document.body.onclick = () => this.method();
Here are several ways to access the parent context inside a child context -
You can use the bind() function.
Store a reference to context/this inside another variable (see the below example).
Use ES6 Arrow functions.
Alter the code, function design, and architecture - for this you should have command over design patterns in JavaScript.
1. Use the bind() function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
If you are using Underscore.js - http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2. Store a reference to context/this inside another variable
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3. Arrow function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
It's all in the "magic" syntax of calling a method:
object.property();
When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:
var f = object.property;
f();
When you get the reference of a method, it's no longer attached to the object. It's just a reference to a plain function. The same happens when you get the reference to use as a callback:
this.saveNextLevelData(this.setAll);
That's where you would bind the context to the function:
this.saveNextLevelData(this.setAll.bind(this));
If you are using jQuery you should use the $.proxy method instead, as bind is not supported in all browsers:
this.saveNextLevelData($.proxy(this.setAll, this));
You should know about "this" Keyword.
As per my view you can implement "this" in three ways
(Self|Arrow function|Bind Method)
A function's this keyword behaves a little differently in JavaScript compared to other languages.
It also has some differences between strict mode and non-strict mode.
In most cases, the value of this is determined by how a function is called.
It can't be set by assignment during execution, and it may be different each time the function is called.
ES5 introduced the bind() method to set the value of a function's this regardless of how it's called,
And ES2015 introduced arrow functions that don't provide their own this binding (it retains this value of the enclosing lexical context).
Method1: Self - Self is being used to maintain a reference to the original this even as the context is changing. It's a technique often used in event handlers (especially in closures).
Reference: this
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function () {
alert(self.data);
});
}
Method2: Arrow function - An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords.
Arrow function expressions are ill-suited as methods, and they cannot be used as constructors.
Reference: Arrow function expressions
function MyConstructor(data, transport) {
this.data = data;
transport.on('data',()=> {
alert(this.data);
});
}
Method 3: Bind - The bind() method creates a new function that, when called, has its this keyword set to the provided value with a given sequence of arguments preceding any provided when the new function is called.
Reference: Function.prototype.bind()
function MyConstructor(data, transport) {
this.data = data;
transport.on('data',(function() {
alert(this.data);
}).bind(this);
The trouble with "context"
The term "context" is sometimes used to refer to the object referenced by this. Its use is inappropriate, because it doesn't fit either semantically or technically with ECMAScript's this.
"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope, and this within the scope of some executing code.
This is shown in ECMA-262 section 10.4.2:
Set the ThisBinding to the same value as the ThisBinding of the
calling execution context
Which clearly indicates that this is part of an execution context.
An execution context provides the surrounding information that adds meaning to the code that is being executed. It includes much more information than just the thisBinding.
The value of this isn't "context". It's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.
First, you need to have a clear understanding of scope and behaviour of the this keyword in the context of scope.
this & scope:
There are two types of scope in JavaScript. They are:
Global Scope
Function Scope
In short, global scope refers to the window object. Variables declared in a global scope are accessible from anywhere.
On the other hand, function scope resides inside of a function. A variable declared inside a function cannot be accessed from the outside world normally.
The this keyword in the global scope refers to the window object. this inside a function also refers to the window object. So this will always refer to the window until we find a way to manipulate this to indicate a context of our own choosing.
--------------------------------------------------------------------------------
- -
- Global Scope -
- (globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // Outer function scope -
- // Inside the outer function, the "this" keyword -
- // refers to window object -
- callback() // "this" inside callback also refers to the window object -
- } -
- -
- function callback_function(){ -
- -
- // Function to be passed as callback -
- -
- // Here "THIS" refers to the window object also -
- } -
- -
- outer_function(callback_function) -
- // Invoke with callback -
- -
--------------------------------------------------------------------------------
Different ways to manipulate this inside callback functions:
Here I have a constructor function called Person. It has a property called name and four method called sayNameVersion1, sayNameVersion2, sayNameVersion3, and sayNameVersion4. All four of them has one specific task. Accept a callback and invoke it. The callback has a specific task which is to log the name property of an instance of Person constructor function.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// Function to be used as callback
var parentObject = this
console.log(parentObject)
}
Now let's create an instance from person constructor and invoke different versions of sayNameVersionX (X refers to 1,2,3,4) method with niceCallback to see how many ways we can manipulate the this inside callback to refer to the person instance.
var p1 = new Person('zami') // Create an instance of Person constructor
bind:
What bind do is to create a new function with the this keyword set to the provided value.
sayNameVersion1 and sayNameVersion2 use bind to manipulate this of the callback function.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
The first one binds this with a callback inside the method itself. And for the second one, the callback is passed with the object bound to it.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
call:
The first argument of the call method is used as this inside the function that is invoked with call attached to it.
sayNameVersion3 uses call to manipulate the this to refer to the person object that we created, instead of the window object.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
And it is called like the following:
p1.sayNameVersion3(niceCallback)
apply:
Similar to call, the first argument of apply refers to the object that will be indicated by the this keyword.
sayNameVersion4 uses apply to manipulate this to refer to a person object
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
And it is called like the following. Simply the callback is passed,
p1.sayNameVersion4(niceCallback)
We can not bind this to setTimeout(), as it always executes with the global object (Window). If you want to access the this context in the callback function then by using bind() to the callback function, we can achieve it as:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
The question revolves around how the this keyword behaves in JavaScript. this behaves differently as below,
The value of this is usually determined by a function execution context.
In the global scope, this refers to the global object (the window object).
If strict mode is enabled for any function then the value of this will be undefined as in strict mode, global object refers to undefined in place of the window object.
The object that is standing before the dot is what the this keyword will be bound to.
We can set the value of this explicitly with call(), bind(), and apply()
When the new keyword is used (a constructor), this is bound to the new object being created.
Arrow functions don’t bind this — instead, this is bound lexically (i.e., based on the original context)
As most of the answers suggest, we can use the arrow function or bind() Method or Self var. I would quote a point about lambdas (arrow function) from Google JavaScript Style Guide
Prefer using arrow functions over f.bind(this), and especially over
goog.bind(f, this). Avoid writing const self = this. Arrow functions
are particularly useful for callbacks, which sometimes pass unexpectedly
additional arguments.
Google clearly recommends using lambdas rather than bind or const self = this
So the best solution would be to use lambdas as below,
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
References:
https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c
arrow-functions-vs-bind
Currently there is another approach possible if classes are used in code.
With support of class fields, it's possible to make it the following way:
class someView {
onSomeInputKeyUp = (event) => {
console.log(this); // This refers to the correct value
// ....
someInitMethod() {
//...
someInput.addEventListener('input', this.onSomeInputKeyUp)
For sure under the hood it's all the old good arrow function that binds context, but in this form it looks much more clear that explicit binding.
Since it's a Stage 3 Proposal, you will need Babel and appropriate Babel plugin to process it as for now (08/2018).
I was facing a problem with Ngx line chart xAxisTickFormatting function which was called from HTML like this: [xAxisTickFormatting]="xFormat".
I was unable to access my component's variable from the function declared. This solution helped me to resolve the issue to find the correct this.
Instead of using the function like this:
xFormat (value): string {
return value.toString() + this.oneComponentVariable; //gives wrong result
}
Use this:
xFormat = (value) => {
// console.log(this);
// now you have access to your component variables
return value + this.oneComponentVariable
}
Another approach, which is the standard way since DOM2 to bind this within the event listener, that let you always remove the listener (among other benefits), is the handleEvent(evt) method from the EventListener interface:
var obj = {
handleEvent(e) {
// always true
console.log(this === obj);
}
};
document.body.addEventListener('click', obj);
Detailed information about using handleEvent can be found here: DOM handleEvent: a cross-platform standard since year 2000
Some other people have touched on how to use the .bind() method, but specifically here is how you can use it with .then() if anyone is having trouble getting them to work together:
someFunction()
.then(function(response) {
//'this' wasn't accessible here before but now it is
}.bind(this))
As mentioned in the comments, an alternative would be to use an arrow function that doesn't have its own 'this' value
someFunction()
.then((response)=>{
//'this' was always accessible here
})
this in JavaScript:
The value of this in JavaScript is 100% determined by how a function is called, and not how it is defined. We can relatively easily find the value of this by the 'left of the dot rule':
When the function is created using the function keyword the value of this is the object left of the dot of the function which is called
If there is no object left of the dot then the value of this inside a function is often the global object (global in Node.js and window in a browser). I wouldn't recommend using the this keyword here because it is less explicit than using something like window!
There exist certain constructs like arrow functions and functions created using the Function.prototype.bind() a function that can fix the value of this. These are exceptions of the rule, but they are really helpful to fix the value of this.
Example in Node.js
module.exports.data = 'module data';
// This outside a function in node refers to module.exports object
console.log(this);
const obj1 = {
data: "obj1 data",
met1: function () {
console.log(this.data);
},
met2: () => {
console.log(this.data);
},
};
const obj2 = {
data: "obj2 data",
test1: function () {
console.log(this.data);
},
test2: function () {
console.log(this.data);
}.bind(obj1),
test3: obj1.met1,
test4: obj1.met2,
};
obj2.test1();
obj2.test2();
obj2.test3();
obj2.test4();
obj1.met1.call(obj2);
Output:
Let me walk you through the outputs one by one (ignoring the first log starting from the second):
this is obj2 because of the left of the dot rule, we can see how test1 is called obj2.test1();. obj2 is left of the dot and thus the this value.
Even though obj2 is left of the dot, test2 is bound to obj1 via the bind() method. The this value is obj1.
obj2 is left of the dot from the function which is called: obj2.test3(). Therefore obj2 will be the value of this.
In this case: obj2.test4() obj2 is left of the dot. However, arrow functions don't have their own this binding. Therefore it will bind to the this value of the outer scope which is the module.exports an object which was logged in the beginning.
We can also specify the value of this by using the call function. Here we can pass in the desired this value as an argument, which is obj2 in this case.

Getting around async issue in node.js application command line

My application is a simple mysql client used from command line - it connects to database and makes few queries to get information from database. Mysql functionality is encapsulated in a class and problem is since calls to mysql server is async (understandably) - the code flow reaches end of application.
And I am unable to refer to 'this'(Mysql) inside a method of Mysql class.
How do I get around this problem ?
Below is my code.
//CLASS
function Mysql(config) {
//...
}
//METHOD
Mysql.prototype.getDbInfo = function (cbk) {
this.showTables(function(e,r) {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(this.configVar);
});
}
module.exports = Mysql;
//CLASS OBJECT
var test = new Mysql(config);
//METHOD INVOKE
test.getDbInfo(function (err,results) {
//...
});
Every time that you jump into a callback function you are loosing the scope of the this object. There are different ways to work around it.
Assign this to another variable
The first solution is to assign the this object to another variable (e.g.: that, self). When you assign one variable to another and the first variable is an object then you keep the reference to the original object and you can use it within the callback. Something like that:
Mysql.prototype.getDbInfo = function (cbk) {
var self = this;
self.showTables(function(e,r) {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(self.configVar);
});
}
Bind the this object to the function
You can bind the this object to the function and like that you set the this keyword set to the provided value (in your case the scope outside of showTables function). You can read the documentation of this and you will be able to understand more:
Mysql.prototype.getDbInfo = function (cbk) {
this.showTables(function(e,r) {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(self.configVar);
}.bind(this));
}
Use es6 arrow functions
It is more or less the same solution like the first one. If you use a transpiler you will find out that it is translated like the first solution:
Mysql.prototype.getDbInfo = function (cbk) {
self.showTables((e,r) => {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(this.configVar);
});
}

what should nodeJS/commonJS module.exports return

I know that I can set module.exports to either an object or a function
(and in some cases a function that will return an object).
I am also aware of the differences and ways to use exports vs. module.exports so no need to comment on that.
I also understand that whatever is returned is cached and will be returned on any consecutive call to require. So that if I choose to return a function and not an object then possibly this implies that on every require It is necessary to actually run this function.
I was wondering is there any defacto standard on which of those two should be used. Or if there is no such standard - what considerations would apply when deciding if my module should return an object, a function or anything more complicated...
The module I intend to write is expected to be used as part of an express application if it matters (maybe there is a "local defacto standard" for express/connect modules).
If the require'd code is standalone, and does not need access to any objects from the parent code, I export an object.
edit - the above is my preferred way to do it. I do the below only when I need to pass stuff into the module, like configuration data, or my database object. I haven't found a more elegant way to give the module access to variables that are in the parents' scope.
So to pass an object from parent into module I use a function:
//parent.js
var config = { DBname:'bar' };
var child = require('./child.js')(config);
//child.js
module.exports = function(cfg){
var innerchild = {};
innerchild.blah = function(){
console.log(cfg.DBname); // this is out of scope unless you pass it in
}
return innerchild;
};
"so that if I choose to return a function and not an object then
possibly this implies that on every require It is necessary to
actually run this function."
It does not matter whether you return an individual function or an object. In neither cases a function (or functions) are ran. unless you explicitly do so.
For instance, consider the a module hello.js:
exports = function () { return 'Hello'; };
You can use require to get that function:
var hello = require('hello');
If you want to run that function, you need to invoke it explicitly as follows:
var hello = require('hello')();
You wrote you want to make sure your function is executed exactly once. Intuitively this could lead you to writing your hello.js as follows:
var hello = function () { return 'Hello'; };
exports = hello();
In which case you could just store result from hello via require:
var hello = require('hello');
However: if you do that the export system may cache your module. In such cases, you do not get fresh result from hello, but instead, a cached value. This may or may not be what you want. If you want to make sure a function is invoked every time it is required, you need to export a function and call it after require.

Resources