Using this vs using variable in JS - javascript

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.

Related

How to test an internal function

I'm trying to create a unit test to cover an internal function
fileA.js
module.exports.functionA = () {
const functionB = () {
// do something
}
functionB()
}
test.js
const { functionA } = require('fileA')
...
it('runs functionB', () => {
functionA()
expect(...).toHaveBeenCalled()
}
How do I access it?
There are two possibilities here (your situation looks like the first one, but is also clearly simplified for the purposes of the question).
Either:
functionB is entirely private to functionA, part of its implementation, which means you can't access it to test it (directly). Instead, test functionA, which presumably uses functionB as part of the work it does (otherwise, there's no point in an entirely private function in functionA).
or
functionA exposes functionB in some way (for instance, as a return value, or as a method on a returned object, or by setting it on an object that's passed in, etc.), in which case you can get it in whatever way functionA provides and then test it.
(Again, I think yours is the first case.)

Should I follow Visual Studio Code suggesting a convert to named function in javascript?

I use the arrow function style quite alot in my ReactJS apps (all of them use functional style with hooks).
const handleKeyDown = (e) => {
doStuff(e.keyCode);
}
Visual Studio Code keeps suggesting here, that I use a named function like:
function handleKeyDown(e) {
doStuff(e.keyCode);
}
What's best practice here? I have read, that arrow function and named function are equivalent in javascript. Is this not true? Does using named function have any benefit here?
There are two major differences.
The first:
function handleKeyDown(e) {
doStuff(e.keyCode);
}
Here you're using a function declaration (or function statement); in the case of arrow function:
const handleKeyDown = (e) => {
doStuff(e.keyCode);
}
You're using a function expression. In fact, they're called arrow function expressions (since there is not an "arrow function declaration", their nature is to be an expression).
So to be clearer, the arrow function version it's more like:
const handleKeyDown = function(e) {
doStuff(e.keyCode);
}
So the first difference is function declarations vs function expression, ( and therefore the difference between statement and expression: Javascript: difference between a statement and an expression?)
For what concerns the functions, function declarations are hoisted where function expressions are not. That's meaning that a code like that:
handleKeyDown({keyCode: 13});
function handleKeyDown(e) {
doStuff(e.keyCode);
}
Is perfectly valid (and running), where a code like that:
handleKeyDown({keyCode: 13});
const handleKeyDown = (e) => {
doStuff(e.keyCode);
}
Will raise an exception because handleKeyDown is not initialized yet.
Another difference between function expression and function declarations was that a function expression it was anonymous (unnamed). This is not valid anymore since the js engine is now able to determined the name associated with them:
const foo = () => {}
const bar = function() {}
console.log(foo.name) // "foo"
console.log(bar.name) // "bar"
However, the difference between arrow functions and function expressions, in this case, is that you can override it:
const bar = function baz() {};
console.log(bar.name) // baz
It's important to notice, however, that the name baz is scoped to the function's body block. It means is not available outside:
const bar = function baz() {
console.log("my name is:", baz.name)
}
console.log(bar.name) // "baz"
bar() // "my name is: baz"
baz() // ReferenceError: bar is not defined
This can be useful when you want to have a recursive function without pollute the outer scope with it. Common examples are setTimeout:
setTimeout(function foo() {
doStuff();
let time = calcNewTime();
setTimeout(foo, time)
}, 1000);
or a RequestAnimationFrame:
requestAnimationFrame(function render() {
updateCoordinates();
renderGameScene();
requestAnimationFrame(render);
});
Said that, the second major difference using arrow functions expressions instead of functions (expression or statement) is the nature of arrow functions itself. MDN has a neat list:
Does not have its own bindings to this or super, and should not be used as methods.
Does not have arguments (object), or new.target keywords.
Not suitable for call, apply and bind methods, which generally rely on establishing a scope.
Can not be used as constructors.
Can not use yield, within its body.
The reason why they're not suitable for call, apply and bind is because they use the contextual object of the enclosing scope when defined; basically they don't have a this on their own. It's well seen when you use them as event handlers:
const obj = {
handleClick() {
console.log("I clicked ", this)
}
}
button.addEventListener("click", obj.handleClick);
button.click(); // "HTMLButtonElement"
Where:
const obj = {
handleClick: () => {
console.log("I clicked ", this)
}
}
button.addEventListener("click", obj.handleClick);
button.click(); // "Window", assuming you execute this code in a browser
To sum up, where there is definitely an area of overlapping between every way to define a callable function, each of them has its own characteristics to known in order to use them correctly, and avoid possible nasty bugs.
Depends, in the majority of cases they do the same (arrow or named functions) BUT they have a difference, the arrow function doesn't have this, so it will look for in the closes parent scope that he can find it, but named functions have their own context.
Honestly, I don't know why VSCode is proposing that change, but depending if you are using class components or functional components using arrow functions can be better.
note, I don't use class components now, but this example is for the people still using that.
import React from 'react';
class SomeComponent extends React.Component {
constructor(props) {
super(props);
this._clickHandlerNamed = this._clickHandlerNamed.bind(this);
this.myText = 'Some text';
}
_clickHandlerNamed(e) {
console.log(this.myText);
}
_clickHandlerArrow = e => console.log(this.myText);
render() {
return(
<div>
<button onClick={this._clickHandlerNamed}>Named Function</button>
<button onClick={this._clickHandlerArrow}>Arrow Function</button>
</div>
);
}
}
As you see in the constructor we are overriding the original this._clickHandlerNamed with a new function that instead of having his own this context, is using the context of the parent class, and this allows to access the this.myText property of the SomeComponent component.
Arrow functions don't have context, so is going to look for the closest this in the tree, so should be able to access the this.myText property.

the "const something = () => ({..." arrow function pattern

The first way:
const logger = () => ({
log(msg) {
console.log(msg)
}
})
class Component {
constructor() {
Object.assign(this, logger())
}
}
The second way:
const logger = {
log(msg) {
console.log(msg)
}
}
class Component {
constructor() {
Object.assign(this, logger)
}
}
Now, what is the difference between the two?
const obj = new Component()
obj.log('what is the difference?')
I see the first piece of pattern multiple times in people's code. Is there a name for this IFFE-ish pattern? In what scenario do we use this pattern?
I simplified it to the second piece of code, still works. It seems to work the same?
The first example creates a new object (and a new log function) every time an instance of Component is created.
The second example reuses the same one each time (so any changes to log would be shared).
In short, they will yield the same result on your example. That's because Object.assign itself will always return a new object, which is composed by the objects you passed as arguments. In both cases you are calling it with the same arguments, being the case you are invoking a factory function to create the object, or if you are passing a simple object literal, so any mutation on the instance objects will not affect the original object.
Object.assign documentation
The difference being that on the second case, the log function is shared across all instances, that's because running a factory function will create a new object every time, therefore a new function, but having it inside of an object and referencing the object will return the same function.
The first approach would be useful if you had to pass in arguments to create a dynamic object based on them. The danger of this approach is that because you are returning a new function every time, you could potentially be creating some performance issues depending how many instances you intend to create. You could solve this problem by having a third option
const log = (msg) => console.log(msg);
const logger = () => ({ log });
class Component {
constructor() {
Object.assign(this, logger())
}
}

Declare class in function argument in Javascript

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.

Solutions for binding JS objects for callbacks

I find that it's very common to have code like (this is TypeScript, but the equivalent JS is fairly obvious and this is really a JS problem, although one that TS could solve):
class Foo {
someField;
someMethod() {
doSomethingTakingACallback(function() {
this.someField; // Fails because `this` is not the instance of `Foo`
});
}
}
The solution, of course, is to use Function.bind() like so:
someMethod() {
doSomethingTakingACallback(function() {
this.someField; // Works as expected
}.bind(this));
}
Now the problem is that I have callbacks that must access the object instance a lot (ie, I need to be calling bind(this) on many callbacks). I've now wasted more time on bugs resulting from this than I'd like to admit. Is there some alternative? Am I missing some easier way to do this? Is there any reason that this is the default behavior as opposed to the function that we get from calling bind(this)?
One solution I know of is to do something like var me = this and then call me.someField (etc). It's a little nicer looking when I have many callbacks or nested callbacks. Although then I lose out on the iconicness of this, which I feel makes it the most clear where the member is located (on the class that I'm writing).
Typescript and ES6/ES2015 both support the "fat arrow function" syntax, which allows you to use this the way you do in most other languages - to refer to the class instance object.
e.g.
someMethod() {
doSomethingTakingACallback(() => {
this.someField;
});
}
This compiles to the following code:
Foo.prototype.someMethod = function () {
var _this = this;
doSomethingTakingACallback(function () {
_this.someField;
});
};
ES6 Arrow functions keep the this of the surrounding scope and thus do not need binding.
ES7 will (possibly) have the :: bind operator
Assign this to another variable outside of your callback method and use that.
class Foo {
someField : any;
someMethod() {
var that = this;
doSomethingTakingACallback(function () {
// use that.someField;
});
}
}

Categories