I am trying to test this module:
function fa(){
return "function A"
}
function fb(){
return "function B + " + fa()
}
module.exports = {fa, fb}
I test it this way:
var myModule = require("./myModule")
var sinon = require("sinon")
var util = require('util');
sinon.stub(myModule,"fa").returns("stub")
console.log(myModule.fb()) //expect to display "function B + stub"
It is actually displaying "function B + function A"
If i replace the method body of fb by return "function B + " + this.fa() (notice the addition of this.) then it works as expected.
Is there a way to mock a function which haven't been called with this?
There is no handy way to do that. You can create an object and use it as a reference, so you call that function as a "method"
What happens is that you are calling that function "as function", the function itself is different from the one that you are exporting.
This read can clarify more about what I said.
Understanding 'this' keyword
Related
I have this code and wondering how can we access properties and method of IIFE
var app = (function () {
function app() {
this.name = 'fasf';
}
app.prototype.greeting = function () {
this.a = 'hello world';
console.log(name);
window.alert('hello world');
};
app.prototype.sayhello = function () {
var j = 't';
console.log(this.a);
};
return app;
}());
also about this piece of code
var t = (function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
})();
With the code you have, you can just do this:
// create an instance of the app object
var a = new app();
// call methods on it
a.greeting();
a.sayhello();
Your IIFE returns the internal app constructor function and then assigns that to a variable named app. So you can then do new app() to create an instance of that object. Once you create an instance of that object, you can then call any of the methods on the prototype.
In your second IIFE, nothing is returned from the IIFE so t is undefined.
The IIFE itself does not have properties and methods. That's just an immediately invoked function expression. In your first one, it returns a constructor function which is then assigned to a variable so that variable can be used to create objects with that constructor function. There are no properties or methods of the IIFE itself.
The way the IIFE pattern works is that you use local variables for the stuff you want to keep private. Local variables are are only visible inside the function they were defined in they cannot be read or written from anywhere else in the program.
If you want to expose things inside the IIFE outside the IIFE one way to do it is via the return value of the immediately-invoked function:
var stuff = (function(){
// These variables and functions are not
// visible from the outside:
var myvar1 = "Hello";
var myvar2 = "World";
var func1(){
return myvar1 + " " + myvar2;
}
// But we can return a record that contains a
// reference to our private functions, making them
// visible outside this block.
return {
thefunc: func1
}
}());
//Now we can call the "thefunc" function we exported
console.log( stuff.thefunc() );
I made sure to not repeat any variable names to avoid confusion.
In your first example, there isn't much of a point to using the IIFE pattern since there are no local variables that you are making private. You could have just defined the app function outside the IIFE and it would have worked the same.
The second case could have been written more clearly by putting the function in a separate line:
function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
}
var t = greet();
Not only is it a bit weird to immediately invoke a named function but in your particular example, the "default argument value" pattern suggests that this function was designed to be called multiple times, sometimes passing the "name" argument and sometimes not passing it (in which case it defaults to the "enter your name" string.
When using IIFE pattern (closure) you usually keep local variables and function private as properly mentions by hugomg's answer.
In case you need to selectively make public some specific property you could consider using "The Revealing Module Pattern" instead, more info here.
Below a simple example showing this pattern:
var app = (function () {
var privateVar = 'hello world';
function sayhelloPrivate() {
console.log(privateVar);
}
function sayhelloPublic() {
console.log(privateVar);
}
// reveal public pointers to
// private functions and properties
return {
sayhello : sayhelloPublic
};
})();
app.sayhello();
//app.sayhelloPrivate(); this will not work as function is private and not visible outside module
I've created a function and bound the arguments as below.
function myFunc(){}
let boundFunc = myFunc.bind(argument);
But then I pass this bound function as an argument to another function, where I need to get the name. The following:
function doTheThing(callable){
console.log(callable.name + " did the thing");
}
doTheThing(boundFunc);
Prints out bound did the thing rather than myFunc did the thing. Is there any way to get the name of the bound function?
callable.caller results in Uncaught TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context. and is not browser standard.
Google Chrome v 51.0.2704.103 gives a different result:
function myFunc(){}
let boundFunc = myFunc.bind(null);
function doTheThing(callable){
console.log(callable.name + " did the thing");
}
doTheThing(boundFunc);
It prints bound myFunc did the thing, so you could get the original name with callable.name.substring(6)
Long story short callable.name does work, and produces bound myFunc.
My version wasn't working because I was using transpiled typescript. This snippet:
class MyClass{
static doTheThing(callable) {}
}
let myFunc = MyClass.doTheThing.bind(null);
function handleCall(callable){
console.log(callable.name)
}
handleCall(myFunc);
produces:
var MyClass = (function () {
function MyClass() {
}
MyClass.doTheThing = function (callable) {};
return MyClass;
}());
var myFunc = MyClass.doTheThing.bind(null);
function handleCall(callable) {
console.log(callable.name);
}
handleCall(myFunc);
The key is the line MyClass.doTheThing = function (callable) {}; This makes MyClass.doTheThing an anonymous function therefore returning undefined for it's name. This results in callable.name returning "bound " + undefined or "bound ".
So in short, you can get the name of a bound function, but a girl function does not have a name.
If you're using node (tested now on v9.2.0), try
import util from 'util'
function myFunc(){}
let boundFunc = myFunc.bind(null)
let functionInfo = util.format(boundFunc)
console.log(functionInfo) // [Function: bound myFunc]
.. and extract it from there
I am just a little confused on why I get the output of [Function] when I am executing a function that I created.
var nameString = function (name) {
return "Hi, I am" + " " + name;
};
nameString("Yasser");
console.log(nameString);
I understand that I am using the function within console.log to print out the value of it. Is it not supposed to print out my name "yasser" instead of saying function?
When you do console.log(nameString), it will just print the output of .toString() called on that function like nameString.toString(). The output of this will be [Function]
You need to execute the function nameString with string argument and then log the returned output as follows
console.log(nameString("Yasser"))
Because you are running console.log on the function, you are not calling it, so you wont get the return value. I see you have called the function above the console.log, but you have not assigned the value anywhere
try
console.log(nameString("Yasser"));
or
var s = nameString("Yasser");
console.log(s);
You are returning a string from your function but not assigning it to anything.
When you console.log you are not using the result of the previous call; you are simply printing what is, in effect in Javascript, a function pointer.
To fix this you should assign the result to a variable:
var name = nameString("Yasser");
console.log(name);
Or simply inline the result of the function:
console.log(nameString("Yasser"));
Very basic thing for you to understand in the Javascript code shared, There are two things to be considered:
Function Reference ----> nameString is the just a reference to the function. Nothing more!
Check this:
http://jsfiddle.net/d73heoL2/1/
var nameString = function (name) {
return "Hi, I am" + " " + name;
};
alert(typeof nameString);
Function call----> For a function to execute, you need to call it. For ex:
nameString();
Having said that, what you wanted can be achieved like this:
var nameString = function (name) {
return "Hi, I am" + " " + name;
};
alert(nameString('WooCommerce'));
Update
The code for the function / class is stored in a string which is why I cannot call it directly. The idea is to do introspection on the object and enumerate its data members which works when it is a function but doesn't work when a variable like the one below is eval'ed.
I am trying to evaluate an object in javascript. Something like this.
var myObj {
greet: "Greeting",
myPrint: function() {
alert("hello");
}
};
The idea is to be able to run this in eval and get the variable name somehow (myObj) or an object created. I have experimented with various methods using eval but cannot figure this out. This works when I have something like this.
function myObj() {
this.greet = "Greeting";
this.myPrint = function() {
alert("hello");
}
};
Running eval("(" + code + ")"); where code is a string containing the above function returns myObj() to me.
Update 2
So basically I want to evaluate something like this.
eval("var x = 5"); and I am trying to get x. Since its a string being evaluated, even though it gets added to the window namespace, there is no way to decipher it apart from parsing the string. Now this is just a simple example but as I said, it's a little difficult with the 1st piece of code. As I said...
eval("function test() { return 'hello'; }"); return test() which is similar to what I am expecting for the "var x = 5" statement.
Is there a way to do this similarly for the 1st case which I am missing ?
Thanks
A code:
var sCode = '{ great: "Greating", myPrint: function() { alert("hello!"); } }',
oObj = eval("(" + sCode + ")");
oObj.myPrint(); // alert "hello"
console.log(oObj.great); // prints "Greating"
Are you trying to dynamically call a callback?
var myObj = { // fixed this line of code as it was missing the =
greet: "Greeting", // replaced ; with ,
myPrint: function() {
alert("hello");
}
};
console.log(eval(myObj)); // returns obj as expected.
If I am correct in my assumption you would need to use bracket notation and EVAL is not needed
So if you were passing a String it would look like:
var str = 'myPrint';
var strTwo = 'greet'
myObj[str](); // to execute the function
myObj[strTwo]; // now contains "Greeting"
Which would execute that function.
Hope that helps!
Tim
EDIT:
var myObj = 'var myObj = { greet: "Greeting", myPrint: function() { alert("hello"); } }'
console.log(eval(myObj));
myObj.myPrint();
Then this is what you want if this does not work it means you are not escaping your string correctly:
http://jsfiddle.net/XtyHh/
You eval the object without executing the myPrint function.
You would need to do something like
myObj.myPrint()
To get it to throw the alert.
[edit] To immediately run the myPrint function change your code to this:
var myObj = {
greet: "Greeting",
myPrint: (function() {
alert("hello");
})();
};
Please consider the example at http://jsfiddle.net/KE8Mv/
HTML
<input type='text' id="log" />
JavaScript
var f = function(){
if(console && console.log)
console.log('hello eval issue!');
}.toString();
var f1 = eval('('+f+')');
var logMsg = f1===undefined?'eval returns none':'eval returns function';
$('#log').val(logMsg);
The eval invoke returns function() object in FF and Chrome, but returns undefined in IE8:(
What might be the issue? How to get the same behavior in all the browsers?
If you really want to do it like this, you can create an anonymous function that will return you the function you need:
var f1 = eval("(function() {return " + f + ";})()");
Edit: Or even simpler (it is only necessary to make the browser consider this an expression with the function being the result of that expression, so we can use the comma operator):
var f1 = eval("0, " + f);
But you might want to consider using the Function constructor that takes the function body as a string.