I'm working on a short JavaScript program, which works perfectly fine ONLY if I inject any trivial statement--such as var asd;--at a specific location. The program is intended to demonstrate a simple encapsulation technique.
No other locations work. ANY trivial statement works.
This is not a DOM load issue since I'm not even dealing with the DOM.
version that works: (warning, 3 alerts)
http://jsfiddle.net/bZUm6/3/
version that does not work:
http://jsfiddle.net/bZUm6/2/
Please note the "var asd;" in the first version.
Can someone please tell me why?
I would really appreciate it.
Max
It's the semicolon removal that's breaking it.
It will work even if you change...
var asd;
simply to this...
;
The reason is that the next line of code starts with (, which happens to be wrapping a function with its closing ).
This is being interpreted as a function call operator, and is attempting to invoke the previous expression.
MyApp.util.toXML = function(options, obj) {
// your code
return result.join("");
}
// var asd; // removing the semicolon
// |------seen as invoking the result of the previous expression and passing
// v the function as an argument.
(function(toXML) {
// your code
})(MyApp.util.toXML);
// ^---------------^ This is then attempting to invoke the return value
// of "toXML", which if it successfully returned, returned a String, which
// can't be invoked.
When you do
MyApp.util.toXML = function(options, obj) {
}
(function(){
}());
you are actually invoking the function
MyApp.util.toXML = function(options, obj) {
}( function(){}()) );
You are forgetting the ; after the function definition
MyApp.util.toXML = function() {
// code
}; // this semicolon
You forgot a semicolon, that's all. See http://jsfiddle.net/bZUm6/6/ (working).
After a function assignment, never forget the ;!
http://jsfiddle.net/bZUm6/8/
You're missing a semicolon after the function. I suppose it evaluates to something else if you don't end the statement.
Related
I have been dealing with issues in multiple pieces of code but it seems to boil down to what I’m showing in this demo. I think it is related to the ’s dereferencing of a closure:
function get_5(callback) {
var result = 5;
callback(result);
}
function get_self(x) {
return x;
}
get_5(console.log);
// 5
console.log(get_self(5));
// 5
In the first result, the first function ran as expected, sending its hidden variable into the input of the console.log function.
The second result also makes sense, as it really just proves the second function works: it takes what was fed in and returns it.
But things get strange when I try to combine the two functions:
var a = get_5(get_self);
console.log(a);
// Undefined!
This third result is undefined, strangely enough, and I am not sure why. Is the closure being dereferenced, maybe to the “sneakiness” of the get_self function? How can I fix this? As a bonus, is there a way to eliminate the get_self function entirely and be able to directly read the variable result, which isn’t modified, without specifying any particular callback?
get_5 has no return statement. It doesn't matter what you pass to get_5, it will always return undefined.
Perl will return the result of evaluating the last statement in a sub, but JavaScript will not.
If you want get_5 to return the result of calling the callback you pass to it, then you have to say so explicitly:
function get_5(callback) {
var result = 5;
return callback(result);
}
Good Day,
I am working on a pet project using NodeJS and Electron. It is basically a simple text editor at the moment. However I am running into an issue when trying to pass the value of a text-area to a function prior to saving to file.
Specifically when I call a function in another module, the value of the contents becomes 'undefined'. I suspect I am passing it incorrectly, or that it is being over-written between when I make the call and when the call executes, since strings are supposed to be passed by reference.
The code for the Renderer(index.html) is like this :
let otherModule = require('./js/otherModule.js');
let $ = require('jquery');
$('#btn_Save').on('click',() => {
// get the fileName, if empty propmt user with save dialog,
//log it to console for debugging
var contents = $('#txt_Content').val();
console.log('with:',contents.substring(0,9),'...');
var finalContents = contents; // (create a copy?)
if(//someConditionMet//)
{
var otherVar = $('#txt_Other').val();
console.log('Use:',otherVar.substring(0,9),'...');
finalContents = otherModule.someFunc(contents, otherVar);
}
//do something with final contents.
})// end of On-click
I have used console.log() to extensively evaluate the function and can confirm that up to the call to otherModule, the contents are correct, and match those in the textArea.It is once we are in the 'otherModule' that things go awry.
The code for the otherModule is like this:
const someFunc = function(contents, otherVar)
{
console.log('DoThings with:',contents.substring(0,9),'...');
// print shows the value to be undefined...
// do more things
console.log('Did stuff with otherVar:',otherVar.substring(0,9),'...');
// prints just fine as as expected.
// do more things
return someString;
}
module.exports = {
someFunc: someFunc
}
As mentioned in the comment, the very first line of the function logs the contents of the console, which displays the substring as 'undefined'.
Thank you for your time and your consideration!
// Extra context//
I have done some searching but beyond learning that strings are passed by reference and are immutable, I have not seen an answer to a question like this. There has been some discussion of closure issues, but usually in the context of events and callbacks, which I do not believe is the context here.
// Extra Information//
I have since found a solution to get my parameters to pass correctly. I have posted the answer below. I did two things:
1. Changed the function definition from 'const' to 'let'
2. Changed the order of the params, and removed the space following the comma.
If you get the value inside the if you should be fine.
if(//someConditionMet//)
{
var contents = $('#txt_Content').val(); //New line
var otherVar = $('#txt_Other').val();
console.log('Use:',otherVar.substring(0,9),'...');
finalContents = otherModule.someFunc(contents, otherVar);
}
I have found a solution to this problem. I am not certain why it makes a difference but I changed two things in 'otherModule'.
1. I changes the function from 'const' to 'let'
2. I changed the order of the parameters, removing the space after the comma
The new function header looks like:
let someFunc = function(otherVar,contents) {...}
I also updated the call to match the new order ( given):
finalContents = otherModule.someFunc(otherVar,contents);
I hope this helps someone in the future!
Is there a method or way in JavaScript that I can check if assert if a function returns a value through the use of an if statement?
So this:
function(val) {
if (val) return "it is true";
return "it is false";
}
versus this:
function(val) {
var str = 'it is ';
return str += val;
}
I've been looking around and can only find articles related to Java or other languages. Thanks in advance.
EDIT: I'm writing tests to assert whether or not a function (written by a user) utilizes an if statement. Hope that clarifies that a bit!
First I'd like to mention that such checks shouldn't be used in code, in which I mean that proper code should never check whether an if-statement is used inside a function. Whether a value is returned from it or not, this shouldn't be checked or tested.
But, to get back on topic. I'm not quite sure whether this is possible out of the box. I do however have a solution that you might be able to use to achieve something similar to your goals.
You can convert a given function to it's string representation. Take a look at the following example:
// Define a function
var myFunction = function() {
return 1 + 3;
};
// Print the function, as a string
console.log(myFunction.toString());
This code will print the string representation of the function in the console, so that will be function() { return 1 + 3; }. Some environments, such as the Firefox return a compiled version of the function which would look like function() { return 4; } but that doens't really have any effect on our use.
Using this method you'll be able to check whether the given function contains an if-statement. Such code would look like this:
// Define a function
var myFunction = function() {
return 1 + 3;
};
// Check whether the given function contains an if-statement
if(myFunction.toString().indexOf('if') > -1) {
console.log('This function does contain an if-statement');
} else {
console.log('This function does not contain an if-statement');
}
This method isn't ideal for your situation but it might point you in the right direction. Please note that this method isn't a rock-solid solution, at least not in this state. The usage of 'if' as a string (or something else) in a function would also cause the code above to say that the function contains an if-statement. Also, this doesn't explicitly check whether a value is returned from inside of an if-statement.
If you'd like to ensure the things mentioned above (that a real if-statement is used, in which a value is returned from it) you might have to modify the above code to make it smarter if this string-based method suits your needs. Then, I'd highly recommend to write a fancy wrapper around it to make it easier in use.
I am just learning NodeJS and/or PhantonJS.
As a programmer with a lot of C experience, I do not like the way NodeJs code is written and find it a bit messy/unreadable. (Sorry if I ruffled any feathers)
In spirit of cleaning up the code, I was trying to do this and found a block.
In C or C++, we should be able to pass a function by name but in NodeJS/PhantomJS it does not seem to work.
Am I doing somthing wrong ?
Can someone explain to me how this is looked at by the Javascript interpreter ?
var page = require('webpage').create();
var printS = function (s) {
console.log(s);
phantom.exit();
}
/* This works */
page.open('http://net.tutsplus.com', function (s) {
console.log(s);
phantom.exit();
});
/* This does not work
page.open('http://net.tutsplus.com', printS(status));
*/
/*But this works
page.open('http://net.tutsplus.com', function (s) { printS(s);} );
*/
page.open('http://net.tutsplus.com', printS(status));
fails because you're not passing the function but rather the result of invoking the function on status. If you want to pass the function, you'd do it this way
page.open('http://net.tutsplus.com', printS);
I thought it might be helpful to have a more extensive explanation. Let's start simple:
In JavaScript, we have values and variables. Variables are containers for values. Almost everywhere where we can use values, we can use variables.
In JavaScript source code, we express values through literals, e.g. the number literal 42. We can directly pass that value to a function:
f(42);
Additionally, instead of passing the value directly, we can pass a variable to the function:
var v = 42;
f(v);
That is, we can substitute values with variables.
Lets consider
var printS = function() { ... };
This clearly is a variable whose value is a function. If we'd directly pass that value to a function (i.e. we pass a function to a function), it would look like:
f(function() { ... }); // similar to f(42)
That's exactly what you have in your first case:
page.open('http://net.tutsplus.com', function (s) {
// ...
});
Since we know that we can replace values with variables, we can just substitute function() { ... } with printS:
var printS = function() { ... }; // similar to var v = 42;
f(printS); // similar to f(v)
So your example would become
page.open('http://net.tutsplus.com', printS);
What is wrong with
page.open('http://net.tutsplus.com', printS(status));
then?
Notice that you added additional characters after printS, namely (status). They don't appear in the your first example where you inlined the function:
page.open('http://net.tutsplus.com', function (s) {
// ...
});
There is no (status) here. Hence these two constructs cannot be not equivalent.
page.open accepts a function value as second argument, but printS(status) doesn't evaluate to the function printS, it calls the function printS and passes the return value to page.open.
Why does
page.open('http://net.tutsplus.com', function (s) { printS(s);} );
work?
Lets remove the content and the argument of the function, and it becomes:
page.open('http://net.tutsplus.com', function () { ... } );
That looks exactly like one of the examples above. function () { ... }, is a function literal, so to speak. It creates a function value. There are no (...) after it which would call the function.
This doesn't work as you hope because page.open wants a function as its second argument... this callback pattern is very common in JavaScript. In your doesn't-work example, printS is being called with status as its argument, and it returns undefined. As undefined is not a function, it doesn't behave as you wish.
In your browser console or the node repl:
> printS = function (s) { console.log(s); };
function (s) { console.log(s); }
> typeof printS('hi');
hi
"undefined"
> typeof function (s) { printS(s); };
"function"
Another thing to know about JavaScript is that its dynamic typing and fairly generous type coercion can result in baffling behavior with no helpful errors to point you towards the root cause of your problem. A debugger or copious use of console.log() is frequently helpful in understanding these sort of problems.
I'm trying to alert any JavaScript object as a string, in a function. This means if the parameter given to the function is window.document, the actual object, it should alert "window.document" (without quotes) as a literal string.
The following calls...
example(window);
example(window.document);
example(document.getElementById('something'));
...calling this function...
function example(o) {/* A little help here please? */}
...should output the following strings...
window
window.document
document.getElementById('something')
I've attempted to do this with combinations of toString() and eval() among some more miscellaneous shots in the dark without success.
No need insane backwards compatibility, newer ECMAScript / JavaScript features/functions are fine. Feel free to inquire for clarifications though the goal should be pretty straight forward.
This is not possible to do in a self contained script.
If using a preprocessor would be an option, then you could write one which converts example(whatever) into example('whatever'). Other than that I'm afraid you're out of luck.
The first problem is that objects don't have names.
The second problem is that from your examples, you're not really wanting to print the (nonexistent) name of an object, you want to print the expression that evaluated into a reference to an object. That's what you're trying to do in this example:
example(document.getElementById('something'));
For that to print document.getElementById('something'), JavaScript would have had to keep the actual text of that expression somewhere that it would make available to you. But it doesn't do that. It merely evaluates the parsed and compiled expression without reference to the original text of the expression.
If you were willing to quote the argument to example(), then of course it would be trivial:
example( "document.getElementById('something')" );
Obviously in this case you could either print the string directly, or eval() it to get the result of the expression.
OTOH, if you want to try a real hack, here's a trick you could use in some very limited circumstances:
function example( value ) {
var code = arguments.callee.caller.toString();
var match = code.match( /example\s*\(\s*(.*)\s*\)/ );
console.log( match && match[1] );
}
function test() {
var a = (1);
example( document.getElementById('body') );
var b = (2);
}
test();
This will print what you wanted:
document.getElementById('body')
(The assignments to a and b in the test() function are just there to verify that the regular expression isn't picking up too much code.)
But this will fail if there's more than one call to example() in the calling function, or if that call is split across more than one line. Also, arguments.callee.caller has been deprecated for some time but is still supported by most browsers as long as you're not in strict mode. I suppose this hack could be useful for some kind of debugging purposes though.
Don't know why you need this, but you can try walking the object tree recursively and compare its nodes with your argument:
function objectName(x) {
function search(x, context, path) {
if(x === context)
return path;
if(typeof context != "object" || seen.indexOf(context) >= 0)
return;
seen.push(context);
for(var p in context) {
var q = search(x, context[p], path + "." + p);
if(q)
return q;
}
}
var seen = [];
return search(x, window, "window");
}
Example:
console.log(objectName(document.body))
prints for me
window.document.activeElement