JavaScript design patterns: Injecting a dependency that is not yet created - javascript

I have a CommonJS module:
// main-module
module.exports = function () {
var foo,
someModule = require('other-module')(foo);
// A value is given to foo after other-module has been initialised
foo = "bar";
}
As you can see, this requires other-module:
// other-module.js
module.exports = function (foo) {
function example() {
console.log(foo);
// > "bar"
}
}
I would like the example function inside of other-module to be aware of the foo variable inside of main-module, even though is it established after the module is required.
When other-module runs, foo will not be undefined. However, the point is that by time my example function runs, foo will have been given a value of bar.
The pattern above obviously does not work. What design pattern do I need to implement?

I'm not super-familiar with CommonJS, so this might not be the idiomatic way to do it, but using a function instead of a variable should work:
// main-module
module.exports = function () {
var foo,
someModule = require('other-module')(function() { return foo; });
foo = "bar";
}
// other-module.js
module.exports = function (fooFn) {
function example() {
console.log(fooFn());
}
}

The foo value (a string) will be passed by value, so it's undefined inside other-module. You could use an options object that is passed by reference:
var options = {},
someModule = require('other-module')(options);
options.foo = "bar";

Related

Is there a way to have a constructor within an already existing constructor?

I have the following function that acts a base constructor:
function Foo() = {}
...
exports Foo
It's an empty constructor, and is used by other functions which I don't want to change. Also, Foo is only being exported from the file.
Now I need to create a different constructor perhaps within Foo.
The following is what I'd have with enum as a standalone constructor. But how do I make it a part of Foo?
function enum(data) {
this.data = data
}
enum.prototype.getVal() { return this.data; }
var obj = new enum(5);
obj.getVal();
Taking a completely wild guess from your commnets.
exporting from the file is of no real concern. If you're just using Foo as a namespace to "hang" functions off of you can do this:
Enum.js
// all constructors should be capitalized
function Enum() { }
Enum.prototype.whatever ...
exports Enum
Foo.js
const Enum = require('./Enum');
// it's unclear why `Foo` is even a function to be honest
function Foo() { }
Foo.Enum = Enum;
exports Foo
someOtherFile.js
const Foo = require('./Foo');
const myEnumInstance = new Foo.Enum();

How to change variable value from another module in javascript

I am using Webpack as bundler and I can't find answer to my question anywhere.
For example, I have file index.js which contains:
import { Func } from './func.js'
export let foo = 'bar';
Func();
console.log(foo);
I have another file, let's say func.js which contains:
import { foo } from './index.js';
export const Func = () => { foo = 'baz' }
But it isn't possible to change value of variable from another module.
How do you handle such situations if I don't want to move function 'Func' to index.js?
I also know it is possible to mutate objects but using an object is not always an option.
foo is a primitive. You can't change it's the value assigned to it in the other module when it's a primitive, you can only change the value foo has been assigned in scope of the current module.
You could always do it with functions however:
let foo = 'initial value';
export const getFoo = () => foo;
export const setFoo = (val) => (foo = val);
import { getFoo, setFoo } from 'someModule';
getFoo(); // initial value;
// call this when necessary
setFoo('jim');
import { getFoo } from 'someModule';
// when called after `setFoo` has been called in the other module
getFoo(); // 'jim'

Test if function of object has been called inside another function in jest

My code looks somewhat like this :
Class A :{
Object foo = new foo;
function (){
...
let var = this.foo.bar()
...
}
And I would like to test with jest that foo.bar() has been called. I've tried with
barSpy = jest.spyOn(function, 'foo.bar');
but it doesn't work, can someone guide me toward the good syntax ?
The parameters for jest.spyOn are the object that contains the function you want to spy on, and the name of the function to spy on (see: https://jestjs.io/docs/en/jest-object.html#jestspyonobject-methodname). It's a little hard to say with the given syntax above, but if foo is available as a property on an instance of A (for this example let's say your instance is called a), then a.foo is the object, and 'bar' is the name of the function.
Here's some code to better illustrate:
class A {
constructor() {
this.foo = new foo();
}
function myFunction() {
...
this.foo.bar();
....
}
}
...
let a = new A();
let barSpy = jest.spyOn(a.foo, 'bar');

Typescript object literal "this" keyword

What's the expected behavior when using this inside a function in an object literal?
For example, let's say I have a type foo that only has a function named bar and no other property on it. But in the fooObj.bar method, I'm able to access this.baz (where baz is not a property on type foo) I see no error. Shouldn't typescript error out, as fooObj does not have baz on it?
type foo = {
bar(): void;
}
var fooObj: foo = {
bar: () => {
// TS does not error out when I access this.baz
console.log(this.baz);
}
}
Setting the "noImplicitThis": true compiler option is how you would enable this functionality now. This pull request enabled typed this in object literals. Aleksey L originally suggested this compiler option in a comment on the question, but at the time it didn't function that way.
You’re using an arrow function, which has lexical this.
The shorthand for a non-arrow function property in an object literal is even shorter, though:
var fooObj: foo = {
bar() {
console.log(this.baz);
}
}
This answer was true at the time of the question. This have since changed with new versions of typescript and target javascript versions.
You are asking typescript to infer that this is fooObj.
Typescript binds this by creating a local variable _this, that is bound to the this-context where the fat-arrow is declared. And in your case, this is the global scope, which is any. This is what it gets compiled into:
var _this = this;
var fooObj = {
bar: function () {
// TS does not error out when I access this.baz
console.log(_this.baz);
}
};
This is how it looks like within a class:
class Bar
{
private var = 23;
public makeSound = () => console.log(this.var)
}
// Compiles into:
var Bar = (function () {
function Bar() {
var _this = this;
this.var = 23;
this.makeSound = function () { return console.log(_this.var); };
}
return Bar;
}());

shared functionality in mocha tests

I put the following code in its own file called shared.js
afterEach(function () {
// insert code
});
var foo;
beforeEach(function () {
foo = {
bar: []
};
});
exports = module.exports = {};
exports.foo = foo;
I'd like the afterEach and beforeEach to be ran in every mocha.js test I have. so in each test file, I required shared.js.
The problem is it seems foo isn't available in the scope of my tests. foo.bar is undefined and inaccessible. The beforeEach() and afterEach hooks are running just fine, but I'm having trouble understanding how to properly export the scope of foo. This might be more of a Node.js problem than an actual Mocha problem.
The problem is that you can not modify the exported reference. In your case you are exporting undefined, because foo is uninitialized. If you initialize foo with an empty object and later try to reassign it to a different thing/object it will still not work because the exported reference is still the same.
The only thing you can do is modifying (mutating) the exported object like so:
afterEach(function () {
// insert code
});
var foo = {};
beforeEach(function () {
foo.bar = [];
});
exports = module.exports = {};
exports.foo = foo;
If you want something that is specific to the context of each test, you can do something like the following:
afterEach(function () {
// insert code
});
beforeEach(function () {
this.foo = [];
});
exports = module.exports = {};
each test can then access its own this.foo:
describe('myTest', function() {
it('should do something', function() {
this.foo.push("1"); // same 'this' as from beforeEach
// ...insert code
})
})

Categories