Why do we do this.xyz inside a function - javascript

I was trying to understand that why do we do this.xyz inside a function?
Like consider this function which we are calling like using foo()
function foo() {
this.value = "Shivom"
console.log(this.value) //Shivom
console.log(value) //Shivom
}
And alternate for this could be
function foo() {
value = "shivom"
console.log(this.value) //shivom
console.log(value) //shivom
}
Similarly, When In react I was using websocket someone asked me to do
class cryptoTicker extends Component {
componentDidMount() {
this.socket = openSocket('https://coincap.io');
let updateCoinData = [...this.props.cryptoLoaded];
this.socket.on('trades', (tradeMsg) => {
componentWillUnmount() {
this.socket.disconnect();
}
Instead of doing something like this
var socket;
class cryptoTicker extends Component {
componentDidMount() {
socket = openSocket('https://coincap.io');
let updateCoinData = [...this.props.cryptoLoaded];
socket.on('trades', (tradeMsg) => {
componentWillUnmount() {
socket.disconnect();
}
[Question:] So when and why do we use this.xyz inside a function? if someone can please explain me using the given two example above?

Well, in a nutshell:
var foo;
function bar(baz) {
foo = baz;
console.log(foo);
}
You can only have one foo value ever in your program this way. It's a singleton/global value.
class Foo {
constructor() {
this.foo = undefined;
}
bar(baz) {
this.foo = baz;
console.log(this.foo);
}
}
let a = new Foo;
let b = new Foo;
a.bar(42);
b.bar('fortytwo');
Using classes and object and setting properties on individual objects (this) allows you to have multiple independent instances of an object/value. That's the basis of OOP.

Related

How should I const inside function when refactoring to class in Javascript

Assuming I have a function that is used as a class:
function Builder() {
const a = somethingThatReturnsAnArray();
this.b = somethingThatReturnsAnotherArray();
this.foo = () => {
a.push('test');
this.b.push('test');
}
}
// Later...
const builder = new Builder();
builder.foo();
Is there any difference between declaring a as a const and b attached to this? Can I convert this function to the class below?
class Builder {
constructor() {
this.a = somethingThatReturnsAnArray();
this.b = somethingThatReturnsAnotherArray();
}
foo() {
this.a.push('test');
this.b.push('test');
}
}
If so is there some caveats in converting everything to class properties?
I guess converting const b = ... to this.b will have some pitfalls, but I'm not sure. What is the correct way to do this? In other words, how should I const inside function when refactoring to class in Javascript?
a should be private in class.
class Builder {
#a = somethingThatReturnsAnArray();
constructor() {
this.b = somethingThatReturnsAnotherArray();
}
foo() {
this.#a.push('test');
this.b.push('test');
}
}

Call all methods in a class when an instance is created

Let's say I have a class that looks like this
class Foo {
bar() {
console.log('bar');
}
baz() {
console.log('baz');
}
// other methods...
}
and I want all of its methods to be unconditionally called whenever a new instance is created. How would I go about that?
I'm currently doing it by calling each method in the class constructor method
class Foo {
constructor() {
this.bar();
this.baz();
// other methods
}
bar() {
console.log('bar');
}
baz() {
console.log('baz');
}
// other methods...
}
here's a snippet of that
class Foo {
constructor() {
this.bar();
this.baz();
// other methods
}
bar() {
console.log('bar');
}
baz() {
console.log('baz');
}
// other methods...
}
new Foo();
Is there a better way to do this?
This seems to be the closest to what I want to achieve. It works by ditching class methods and using IIFEs in classProperties instead.
So something like this
class Foo {
bar = (() => {
console.log('bar');
})()
baz = (() => {
console.log('baz');
})()
}
new Foo();
and it works well on Chrome but the majority of other browsers don't yet have support for classProperties since they were added in ES9
My question is:
If I have a class with a number of methods in it, can I call all of them whenever a new instance of that class is created without having to call each individual method in the constructor method of that class?
In the context of this question, you can completely ignore the need to pass parameters to the methods. I don't need to pass any parameters to any of the class methods.
If the order in which you call the methods is not important, you can iterate dynamically over the properties of your created instance with Object.getOwnPropertyNames method:
class Foo {
constructor() {
return Object.getOwnPropertyNames (Object.getPrototypeOf (this))
.filter(propName => (propName !== 'constructor' && typeof this[propName] === 'function'))
.forEach(propName => this[propName]());
}
bar() {
console.log('bar');
}
baz() {
console.log('baz');
}
// other methods...
}
You can declare function this way:
bar = function() {
console.log('bar');
};
And iterate values of new instance, check for functions and call them:
class Foo {
constructor() {
Object.values(this).forEach(value => {
if (typeof value === 'function') {
value();
}
});
}
nonFunctionProp = 'nfp';
bar = function() {
console.log('bar');
};
baz = function() {
console.log('baz');
};
// other methods...
}
new Foo();

javascript bind does work for function in a dictionary

so I have a function inside a dictionary
const Dict = {
func : () => {
console.log(this);
}
}
class A {
constructor() {
this.fun = Dict.func.bind(this);
}
}
const a = new A();
a.fun();
this gives me undefined, where I'm expecting this to be a
this binding seems to work if I move the function out of the dictionary. why doesn't bind work with dictionary?
Create a function as a property instead of using an arrow function, bind doesn't work for this with arrows
const Dict = {
func() {
console.log(this);
}
}
class A {
constructor() {
this.fun = Dict.func.bind(this);
}
}
const a = new A();
a.fun();

Calling class instance as a function in JavaScript

Assuming I have a class
class foo {
constructor() {
this._pos = 0;
}
bar(arg) {
console.log(arg);
}
}
const obj = new foo();
How do I make it possible to call:
let var1 = obj('something');
You can make a callable object by extending the Function constructor, though if you want it to access the instance created, you'll actually need to create a bound function in the constructor that binds the instance to a function that is returned.
class foo extends Function {
constructor() {
super("...args", "return this.bar(...args)");
this._pos = 0;
return this.bind(this);
}
bar(arg) {
console.log(arg + this._pos);
}
}
const obj = new foo();
let var1 = obj('something ');

inherit javascript function prototype outside it closure

I am using JavaScript prototype chaining technique to chain functions as shown below:
var foo = (function () {
function fn(arg) {
if (!(this instanceof fn)) {
return new fn(arg);
}
this.arg = arg;
return this;
}
var func = function (element) {
return fn(element);
};
fn.prototype = {
bar: function () {
return this;
}
}
func.functions = fn;
return func;
}());
I would like to know how to access fn.prototype so I can add more functionality to the foo prototype outside its closure.
If I just simply do as follows, it won't work:
foo.prototype.baz = function () {
alert(this.arg);
}
foo("hello").baz();
However if fn assigned to the foo (func.functions = fn;) as it shown in the foo private closure I can do as follow and it will works:
foo.functions.prototype.baz = function () {
alert(this.arg);
}
foo("hello").baz();
Is there any other way to achieve this?
I think you are un-necessarily overcomplicating this. You can chain by simply doing this:
const foobar = function(){return this} // Initialize a new Object
const foo = text => {
const me = new foobar()
me.text = text
me.bar = a => (alert(me.text+": "+a), me)
return me
}
foo('A').bar('Test').bar('Test chained')
// Update the foobar class with baz
foobar.prototype.baz = function() {alert('BAZ worked!');return this}
foo('B').bar('1').baz().bar('2')
Note: Click Run code snippet to see the output
That's it!
Edit:
You can also do this with ES6 classes like:
class foobar {
constructor(text) {
this.text = text;
}
bar(a) {alert(this.text+": "+a);return this}
}
const foo = text => new foobar(text)
foo('A').bar('Test').bar('Test chained')
// Update the foobar class with baz
foobar.prototype.baz = function() {alert('BAZ worked!');return this}
foo('B').bar('1').baz().bar('2')

Categories

Resources