I want to make file with four or five exports function.
exports.a = function() {
// some code
};
exports.b = function() {
// need to call function a
};
and I need from second (in this case function b to call function a) to call first exported function, but it ignores call and never enter in first function ( in this case function a).
How to call first exported function from second exported ?
You can do it like this:
var a = exports.a = function() {
// some code
};
exports.b = function() {
a();
};
Or you could use exports.a() in the second function, but this would mean looking up the field a in exports each time. Using var a = ... is faster.
A pattern I often see is something like:
var a = function() {
// ...
};
var b = function() {
var c = a();
// ...
return c; // or whatever
};
// Now decide what declared variables are being exported.
module.exports = {
a: a,
b: b
};
Declare everything you want to use, then export what should be public as the last thing.
Related
I am trying to create function findStrings which should share it's variables with the function init, stringSplit and stringSearch.
String.prototype.findStrings = (function () {
var action = 'split';
var params = ',';
var init = function (action = 'split', params = ',')
{ this.stringSplit(); }
var stringSplit = function (action)
{ return this.init(); }
var stringSearch = function (action)
{return this.init(); }
return init;
})();
What I need.
When I call test.findStrings('split'); it should 1) initiate variables by calling init 2) then call stringSplit so this should be string test.
When I call var result = test.findStrings( 'search', { params ... } ); 1) initiate variables, process arguments from object params 2) then call stringsSearch and this should be test.
var test = '#a > :matches(.b, #c)';
test.findStrings('split', "," );
var result = test.findStrings( 'search', { params ... } );
Error which I got is saying that this does not have stringSplit (because this is Window) and I need to this to be test.
How to access the test string within the functions and make it possible to access the variables and arguments within them?
Actually, I could remove the function searchStrings to simplify it.
Solution:
String.prototype.findStrings = (function () {
var text = this;
...
String.prototype.init = function (action = 'split', params = ',') {
text.stringSplit();
}
}
There were two errors.
I need to this to be test.
When init() is first called, this does equal test. The problem is that stringSplit and stringSearch are just variables, and have nothing to do with the current context.
Either way, the code is pretty difficult to understand. If you really want to override String, then why don't you do something like:
String.prototype.findStrings = function(action = 'split', params = ',') {
// do logic here (not entirely sure what you want to accomplish)
return (action === 'split') ? this.stringSplit() : this.stringSearch();
}
// Add other functions also to string prototype
String.prototype.stringSplit = function() { ... }
String.prototype.stringSearch = function() { ... }
Personally though, I don't like adding methods to types like String for various reasons. Why not adopt a more functional approach, and create functions that you simply pass strings to, and get an appropriate result?
For example:
function findStrings(str, params){
// do logic and return result
}
First of all, you have a circular reference in your code: the init function calls stringSplit which calls init.
But to reach to that problem you should remove the this keyword from your prototype function. this will get the value of the object that is calling your function, in your case the window object, but your functions are created in a closure so you can't access them using the window object.
Imagine I have a fn like this:
var test = (function() {
var self = this;
var a = function() { (function() { self.b() })() }
var b = function() { console.log("hello") }
return { a:a,b:b }
})();
test a function calls the b function inside an another function. However I retained the this as self, still I'm getting issue:
test.a()
Uncaught TypeError: self.b is not a function(anonymous function) # VM246:4a # VM246:4(anonymous function) # VM247:2InjectedScript._evaluateOn # (program):883InjectedScript._evaluateAndWrap # (program):816InjectedScript.evaluate # (program):682
Where I'm making mistake? Why the self isn't retaining the this?
How to solve this issue?
Note
Changing the function to this:
var a = function() { (function() { b() })() }
this works. However I don't want to this way, because, imagine now I'm testing the function a calls function b. Now I want to spy b, if I do :
var spyb = sandbox.spy(test,"b")
and call:
test.a()
in the test code if I try to do the assertion:
assert(b.calledOnce)
this fails, as spy lib couldn't able to figure out test b fn is called.
So kindly help me to get the self way.
this within the anonymous function you use to build test is either undefined (in strict mode) or the global object (in loose mode); neither is what you want.
You don't need an object reference at all to call b from a:
var test = (function() {
var a = function() { (function() { b() })() }
// No need for an object -----------^
var b = function() { console.log("hello") }
return { a:a,b:b }
})();
Since a is a closure over the context of the call to the anonymous function, it has an enduring reference to b (as b does to a).
But if you want to use one, you could do this:
var test = (function() {
var obj = {
a: function() { (function() { obj.b() })() },
b: function() { console.log("hello") }
};
return obj;
})();
when you return
{a:a,b:b,c:self}
you would see 'self == window' is true, so the self is point to window.
but declare variables 'b' in function use 'var' , the scope of 'b' is in the function , not the window , so 'self' cannot reach the variables 'b'.
the correct is :
var test = function() {
var self = this;
self.a = function() { (function() { self.b() })() }
self.b = function() { console.log("hello") }
return { a:self.a,b:self.b }
};
var q = new test();
q.a(); //hello
Can anyone explain to me why "b" returns undefined and how I can get around this problem? Why does the "this" scope get lost when I call prototype functions by reference?
MyClass = function(test) {
this.test = test;
}
MyClass.prototype.myfunc = function() {
return this.test;
}
var a = new MyClass('asd').myfunc();
var b = new MyClass('asd').myfunc;
// Returns "asd" correctly
console.log(a)
// Returns undefined??
console.log(b())
=== EDIT / SOLUTION ===
As plalx writes, the correct solution in my case is to use .bind(). So the result looks like this:
MyClass = function(test) {
this.test = test;
}
MyClass.prototype.myfunc = function() {
return this.test;
}
var a = new MyClass('asd').myfunc();
var b = new MyClass('asd'),
bfunc = b.myfunc.bind(b)
// Returns "asd" correctly
console.log(a)
// Also returns "asd" correctly!
console.log(bfunc())
You need to explicitely bind the this value if you want this behaviour.
var c = new MyClass('asd'),
b = c.myfunc.bind(c);
console.log(b());
By default, this will point to the leftSide.ofTheDot(); in an invocation, or simply the object on which the function was called.
Note: Calling b(); is the same as window.b();.
Binding every function to the object instance is possible but rather inefficient because functions will not get shared across instances anymore.
E.g.
function MyClass(someVal) {
var me = this;
me.someVal = someVal;
me.someFn = function () {
return me.someVal;
};
}
The line var b... is a function reference and you're not actually calling the function.
Here you are assigning to a variable a result of myfunc() function.
var a = new MyClass('asd').myfunc();
And here, you are asigning to b variable function reference, rather then runing it, and assign result to variable.
var b = new MyClass('asd').myfunc;
And finaly here:
console.log(b())
You trying to log result of function b and in that case b() isn't defined anywhere, only it is assigned reference to function.
Try this:
console.log(b); // It logs [Function]
But besides that, your question is hard to understand.
P.S. Use semicolons!
I'm learning node.js and interested in is there any difference between following two cases.
I.E. I have some variable myvar (like db connection or just constant string "test") that needed to be passed in many modules and submodules.
First case.
Create modules, that accept that variable as a param:
submodule.js:
var option
, submodule = {};
submodule.func = function(){
...
var something = option;
...
}
module.exports = function(opts){
option = opts;
return submodule;
}
module1.js:
var option
, submodule
, module1 = {};
module1.func = function(){
...
submodule.func();
...
var something = option;
...
}
module.exports = function(opts){
option = opts;
submodule = require('./submodule')(opts);
return module1;
}
In this case if submodule is used in several modules with same myvar value (i.e. 2 modules) submodule's module.exports function will be called 2 times. In node.js mans it said that "Modules are cached after the first time they are loaded". And I can't understand is this module cached or not.
Another case:
That myvar can be passed as parameter to module functions. So code will look like:
submodule.js:
function func(option){
...
var something = option;
...
};
exports.func = func;
module1.js:
var submodule = require('./submodule');
function func(option){
...
submodule.func(option);
...
var something = option;
...
};
exports.func = func;
So the question is:
Is there any difference between this two cases or they are same?
I'm not exactly sure what you're asking here, but if you need to pass values into your modules you should make sure to export functions that accept parameters. When they say that a module is cached, it means that your module is only initialized once. Think of your module as an object:
var a = 1;
var b = 2;
console.log("init!");
module.exports.test = function(){
console.log("this is a function!");
}
Here, a, b, and the first log will run only once. This is when the module is requested and is then cached. When you do a
var example = require("module")
If it was never created it'll initialize a, b, and do the log message. If it was already created it will just give you a reference to what you exported. Each time you call:
example.test()
It will output: this is a function!
But you will NOT get the a, b, and the first log run again.
Think of all statements not exported as private static variables of that object.
Here is another fully working example:
app.js
var s = require("./sample");
var y = require("./sample");
s.test();
y.test();
s.test();
console.log("finished");
sample.js
var a = 1;
var b = 2;
console.log("init!");
function test() {
console.log("here! " + a);
a++;
}
exports.test = test;
This all outputs:
init!
here! 1
here! 2
here! 3
finished
Does this help at all?
I am having a JavaScript namespace say
A={
CA: function() {
this.B();
},
B: function() {
var test='test';
var result='t1';
C: function() {
this.test='test1';
.....
.....
return 'test1';
}
result=this.C();
return result;
}
}
Now when I am executing such code it is giving that TypeError: this.C is not a function. Can somebody tell me why it is so. I know it is something related with lexical scoping but am unable to understand this.
You have to be careful when you use this to identify anything in Javascript because each time you change scope "this" changes.
Assigning the 'this' reference to it's own variable helps get around this.
var a = new function() {
var self = this;
self.method = function() { alert('hiya'); };
var b = function() {
this.method(); // this isn't 'a' anymore?
self.method(); // but 'self' is still referring to 'a'
};
};
I think the problem is that when this.C() is executed inside the function referred to by B, this refers to the object that contains B, that is, object A. (This assumes B() is called within the context of A)
The problem is, C does not exist on the object A, since it's defined within B. If you want to call a local function C() within B, just use C().
EDIT:
Also, I'm not sure what you've posted is valid JavaScript. Specifically, B should be defined this way, since you can't use the object:property syntax within a function.
B: function()
{
var test='test';
var result='t1';
var C = function()
{
this.test='test1';
return 'test1';
}
result=C();
return result;
}
I am actually surprised that your code doesn't give you error on the 'C:' line.
Anyway, your syntax to define a function is not correct. Define it using the var keyword. Also, notice that I created the 'closure' so that the function C can access 'this'. See the code below:
A={
CA: function()
{
this.B();
},
B: function()
{
var test='test';
var result='t1';
var self = this;
var C = function()
{
self.test='test1';
.....
.....
return 'test1';
}
result=C();
return result;
}
}
If you want to assign C to 'this' object, you can also do:
A={
CA: function()
{
this.B();
},
B: function()
{
var test='test';
var result='t1';
var self = this;
this.C = function()
{
self.test='test1';
.....
.....
return 'test1';
};
result= this.C();
return result;
}
}
Solution for calling methods from another method. (Essentially the pointer "this" must be assigned to a variable and the new variable used in place of this.)
function myfunction(){
var me = this;
me.method1 = function(msg){ alert(msg); }
me.method2 = function(){
me.method1("method1 called from method2");
}
}
var f as new myfunction();
f.method2();
This example shows how one can call a method from within another method or from outside using an instance of the function.