Does there exist a string s such that
(new Function(s))();
and
eval(s);
behave differently? I'm trying to "detect" how a string is being evaluated.
Check for the arguments object. If it exists, you're in the function. If it doesn't it has been evaled.
Note that you'll have to put the check for arguments in a try...catch block like this:
var s = 'try {document.writeln(arguments ? "Function" : "Eval") } catch(e) { document.writeln("Eval!") }';
(new Function(s))();
eval(s);
Demo
Solution to nnnnnn's concern. For this, I've edited the eval function itself:
var _eval = eval;
eval = function (){
// Your custom code here, for when it's eval
_eval.apply(this, arguments);
};
function test(x){
eval("try{ alert(arguments[0]) } catch(e){ alert('Eval detected!'); }");
}
test("In eval, but it wasn't detected");
The current answer does not work in strict mode since you can't redefine eval. Moreover, redefining eval is problematic for many other reasons.
The way to differenciate them is based on the fact that well... one of them creates a function and what doesn't. What can functions do? They can return stuff :)
We can simply exploit that and do something with return:
// is in function
try {
return true;
} catch(e) { // in JS you can catch syntax errors
false; //eval returns the return of the expression.
}
So in example:
var s = "try{ return true; }catch(e){ false; }";
eval(s); // false
Function(s)(); // true
(new Function(s))(); // true, same as line above
(function(){ return eval(s); })(); // the nested 'problematic' case - false
evaled code can be detected by invoking an error and checking if the native stack-trace contains a lower row/column indicator.
if (typeof window === 'object') {
// browser
window.isEvilEval = function () {
return parseInt(String(new Error().stack).split(':').pop(), 10) < 10;
};
} else {
// nodejs (must be global to be callable from within Function)
global.isEvilEval = function () {
return (
new Error().stack
.split('\n')
.filter((l) => l.trim().startsWith('at eval') && l.indexOf('<anonymous>:1') > -1).length > 0
);
};
}
// test - directly in code => false
console.log(isEvilEval());
// test - in evil eval => true
eval('console.log(isEvilEval())');
// test scoped in function => false
Function('console.log(isEvilEval())')();
Related
Is there a way to tell the difference between this
((a=true)=>{return a})(true)
And this?
((a=true)=>{return a})()
They both return true - how can I tell whether that true is coming from the default value of the argument, or from the value passed in to that parameter?
Is it possible from outside the function?
Is it possible from inside the function?
Is there a way to tell the difference between these two?
No. Arrow function doesn't support argument object, so there is no way to check this.
But, if you are using non-arrow functions, you can get arguments number from inside the function. For example:
(function(a=true){return arguments.length;})(); // 0
(function(a=true){return arguments.length;})(true); // 1
You can easily figure out how to extend this to multiple arguments.
You cannot tell the difference in your specific examples, and there is no way to tell from outside the function definitely. The only exposed info is what you explicitly expose with your return value, which is just the boolean.
From inside the function, you can tell the difference if you rewrite your logic. You could change your function from
((a=true)=>{
return a;
})(true)
to
((...args)=>{
const a = args[0] === undefined ? true : args[0];
if (args.length > 0) console.log("passed arg");
else console.log("passed no arg");
return a;
})(true)
Note that you cannot combine this with default value syntax, so if you'd have to rewrite it to use rest syntax.
Alternatively, you could use a normal function instead of an arrow, and use arguments, however that is also a potentially difficult change if your real-world case relies on the arrow-function's lexical this. e.g.
(function(a = true)=>{
if (arguments.length > 0) console.log("passed arg");
else console.log("passed no arg");
return a;
})(true)
Although not ideal in every way, one solution might be:
(a=undefined) => {
let is_default = false;
if (a === undefined) {
is_default = true;
a = true;
}
return a
}
If you really want to use arrow functions, you can achieve a robust (if convoluted) result using Symbol and a wrapping IIFE
var fn = ((def) =>
(a = def) => {
if(a === def) {
console.log('defaulted');
a = true;
}
console.log('a is', a);
}
)(Symbol());
both fn() and fn(true) will result in a is true - however, fn() will also output defaulted and then set a = true - though this last step I guess doesn't have to done, depends on what the real content of the real function you really want to "detect" this in
Or, a better way as pointed out by #Bergi (I keep forgetting about the block scope in ES6+ :D )
var fn;
{
const def = Symbol();
fn = (a=def) => {
if(a === def) {
console.log('defaulted');
a = true;
}
console.log('a is', a);
};
}
Is it possible to break out of an outer function from its inner function?
(function one(){
var foo = (function two(){
if(true){
return true; //all good
}else{
//how can we break function one here?
})();
//extra statements only executed if foo is true
})();
No such thing as "return return" right? :P
UPDATE
Thanks all - as I suspected the "return return" functionality I was looking for is not possible. But with your input/tips I reworked my code and used a try/catch block. There a many ways to skin a cat in JS!
return only applies from within the function it's used.
What you can do is make two() return a boolean.
Than evaluate two() inside an if statement inside one()
function two() {
// Some logic here...
var isError = true; // sometimes is false :)
// Internals
if (isError) {
console.log("Something is wrong");
}
// Finally return a boolean
return isError;
}
(function one(){
// `two()` returns a boolean, true if there's an error.
// `return` will stop furthere execution of `one()`
if( two() ) return;
console.log("This will not log if there was an error")
})();
In your example code, it would be best for the outer function to test foo, but in more complex code, exceptions might be appropriate:
;(function() {
var foo = (function() { return true })()
if (!foo) return;
console.log('reached because foo was true')
})()
;(function() {
try {
;(function() {
var foo = (function() { throw new Error('fail') })()
/* only reached if an error wasn't thrown */
})()
}
catch (error) {
console.log('Something went wrong: ' + error)
}
})()
Output:
reached because foo was true
Something went wrong: Error: fail
This desire might appear more often in JavaScript than in comparable languages because JavaScript's only way to provide scope is with a function body, and you have fewer control-flow options across function boundaries. But if you're using a self-executed function purely to provide a scope, and not keeping the function around to close over the variables, then just don't do that when you run into control-flow situations like this.
The general idea of a function is that it will return a data type for the single function of which it resides. Return is just a language feature used to implement this idea of giving back data from the function. And so the notion of performing a return-return cannot be applied.
But in this paradigm, the problem you are solving is more related to Flow of Control. The solution you choose should be based on how you can most clearly express the idea in your code.
Depending on the reason you ask this question, if you are being challenged by a certain piece of logic in your application, and aren't just asking a technical question about the language, I would recommend posting a code sample which allows us to understand the intention of your goal. Since this is the key factor to choosing the best solution.
Of course you may implement a solution in all sorts of ways. Exceptions, statefulness, or functional solutions. But you need to choose the right tool for the job.
//how can we break function one here?
return false ?
var div = document.querySelector("div");
var buttons = document.querySelectorAll("button");
var process = function process(value) {
return (function one(val) {
var foo = (function two(bool) {
if (bool) {
return true; //all good
} else {
return false //how can we break function one here?
}
})(val);
//extra statements only executed if foo is true
// if `foo` : `true` do stuff
if (foo) alert(foo);
// return `foo`
return foo
})(value)
};
var fn = function(e) {
div.innerHTML = process(e.target.textContent === "false" ? false : true);
}
buttons[0].onclick = fn;
buttons[1].onclick = fn;
<button>true</button>
<button>false</button>
<div></div>
I defined a prototype function 'isElement' of Node and I want to make it works like 'div.isElement' return 'true'.
<div id="dom1">someText
<p>This is p1 of <span class="bold">dom1</span></p>
</div>
Node.prototype.isElement = (function(){
var result;
var fn = function(){
console.log(obj);
result = (this.nodeType == 1 ? true : false);
return result;
};
fn.toString = fn.valueOf = function(){
return result;
};
return fn;
})();
var dom1 = document.getElementById('dom1');
dom1.isElement(); //true
dom1.isElement; //true
If the 'dom1' never call the function 'isElement()',then 'dom1.isElement' return 'undefined'. I understand why it return 'undefined',but I want to know how to makes it return 'true' or 'false' when 'isElement()' never be called.
I just want to use it like:
if(dom1.isElement){//do something}
but not like:
if(dom1.isElement()){//do something}
waiting for answers , thanks.
As mentioned in the comments, the JavaScript language makes no guarantees that the DOM implementation provides the standard JS object facilities.
That said, if you have determined that your environment always supports these then a getter is called for in this case, effectively you can write a function which is called whenever a specific property value is requested.
Refer to MDN for the details :
Node.prototype.__defineGetter__('isElement',
function () { return this.nodeType === 1; });
Test it with your browser at http://jsfiddle.net/L5hBq/
You can add a property that has your function as the getter:
Object.defineProperty(Node.prototype, "isElement", {
get: function() {
var result = this.nodeType == 1;
return result;
}
});
Is there a way to print arguments' list in full or in parts in JavaScript?
Example:
from within the function my_assert(a!=b) I'd like to print a!=b, or even 2!=3 for a particular function call.
you can't. a!=b is executed first and only the result of this (true or false) is given to your function so you don't have a chance to get back a!=b or 2!=3.
console.log (arguments)
will print the arguments given to the function, but in your case, all your function sees is a boolean, because a != b will be evaluated first, and only the result passed as a parameter in the function call.
umm... here, I'll google it for you :)
http://www.seifi.org/javascript/javascript-arguments.html
As some others pointed out, passing in a test (a != b) will only get you a boolean value (true|false) as your argument. But if you call myAssert(a,b), you can then evaluate the arguments and test their equality, as well as print their values, following the advice in the link I pasted.
Here you go:
my_assert = (test) ->
str = my_assert.caller.toString()
match = /return my_assert\((.*)\)/.exec str
console.log match[1], test
a = '1'
b = '2'
do -> my_assert(a!=b)
do -> my_assert(b!=a)
> a !== b true
> b !== a true
http://jsfiddle.net/m7qRN/
The only caveat is you have to call your my_assert calls from separate anonymous functions in order to be able to reliably get the source code of the assertion call.
In CoffeeScript its not so bad using the do -> notation.
In JS this is: (function(){my_assert(a!=b)})();.
You could pass in the test as a function like so:
my_assert -> a!=b
my_assert(function(){a!=b});
//
// A variation on vaughan's answer, from Oct 1 '13
// Includes simple unit test to debug the regex for multiline assert expressions
// Use console.error and/or 'throw new Error' depending how you handle errors
//
function test_assert() {
try {
(function () { assert(3 === 'a') })();
(function () {
assert('foo' !== 'bar')
})();
(function () {
assert('foo' ===
'bar')
})();
} catch (e) {
console.error(e.stack)
}
} // test_assert
function assert(expression) {
if (!expression) {
let caller = assert.caller.toString()
let test = caller.match(/assert[^]*\)/)
//throw new Error(test[0] + ' failed');
console.error('%s failed', test[0])
}
} // assert
/////////////////////////////////
// Here's a simple assert()
function assert2(condition, message) {
if (!condition) {
console.error('assert (%s) failed: "%s"', condition, message)
throw new Error("Assertion failed: " + message);
}
}
You can't do it. When you have the following line:
my_assert(a!=b);
The expression a!=b will first be evaluated and its result will be passed to my_assert.
Assuming your my_assert() function is used specifically for your own testing and you can control how it works and what you pass into it you could do something like this:
my_assert(a!=b, "a!=b");
I.e., pass an extra parameter to the function with a string representation of what is being tested. Obviously that doesn't stop you accidentally saying my_assert(a!=b, "a==b");, and it's clunky, but I can't think of another way to do it.
I'm refactoring a large javascript document that I picked up from an open source project. A number of functions use inconsistent return statements. Here's a simple example of what I mean:
var func = function(param) {
if (!param) {
return;
}
// do stuff
return true;
}
Sometimes the functions return boolean, sometimes strings or other things. Usually they are inconsistently paired with a simple return; statement inside of a conditional.
The problem is that the code is complex. It is a parser that uses a multitude of unique RegEx matches, creates and destroys DOM nodes on the fly, etc. Preliminary testing shows that, in the above example, I could change the return; statement to become return false;, but I'm concerned that I may not realize that it had a negative impact (i.e. some feature stopped working) on the script until much later.
So my questions: Is there a benefit to using a blank return statement? Could this have been intentionally coded this way or was it just lazy? Can I change them all to return false;, or return null; or do I need to dig through every call and find out what they are doing with the results of those functions?
Using return without a value will return the value undefined.
If the value is evaluated as a boolean, undefined will work as false, but if the value for example is compared to false, you will get a different behaviour:
var x; // x is undefined
alert(x); // shows "undefined"
alert(!x); // shows "true"
alert(x==false); // shows "false"
So, while the code should logically return true or false, not true or undefined, you can't just change return; to return false; without checking how the return value is used.
"Blank return" statements can be used to transfer the control back to the calling function (or stop executing a function for some reason - ex: validations etc). In most cases I use blank return statement is when I'm doing some kind of a validation. However, I make it a point to set some indicator as to why the execution of the function is stopped. For example, set the "innerText" property on a DIV element with the error message.
In the code above, it looks like it is a validation. The function returns a "true" if everything went well. It looks like the calling function parses the return value, and if it is "true", next step of statements (in the calling function) are executed.
It is a good practice to return "false" instead of a blank return in the above example. That way you make it all uniform and make life easy for other programmers.
You could fix such inconsistencies; however, make sure you test all the changes thoroughly. It is a good practice to test each change you make to the code, however small it may be.
There is no difference at all between return; and return undefined;. The result of calling both functions is to receive the value undefined.
(There's a very small specification-level difference between a function body that terminates with return vs. just falling off the end of the code, but it's nothing that can be detected in code.¹ Calling a function where execution falls off the end of the code also results in the value undefined.)
"use strict";
// Implicit return of `undefined`
function x() {
return;
}
// Explicit return of `undefined`
function y() {
return undefined;
}
// Execution falls off the end
function z() {
}
console.log(typeof x() === "undefined"); // true
console.log(typeof y() === "undefined"); // true
console.log(typeof z() === "undefined"); // true
Unless, of course, something has shadowed undefined. Which is still sadly possible (though not, gladly, at global scope). In that very edgy edge case, there's a difference:
"use strict";
(function() {
const undefined = 42;
// ^^^^^^^^^^^^^^^---- shadowing `undefined`
// Implicit return of `undefined`
function x() {
return;
}
// Explicit return of `undefined`
function y() {
return undefined;
}
// Execution falls off the end
function z() {
}
console.log(typeof x() === "undefined"); // true, `x` returns the canonical `undefined`
console.log(typeof y() === "undefined"); // false, `y` returns 42
console.log(typeof z() === "undefined"); // true, `z` (effectively) returns the canonical `undefined`
})();
¹ Using return is an abrupt completion that [[Call]] converts to a normal completion w/value. Falling off the end of the code is a normal completion (spec) (that [[Call]] ensures supplies undefined for the value). But again, this is a specification level difference, not something that's observable in code.
What MIGHT be lost here (not direct with your example) is that you can then have a tri-state object:
var myfunc = function(testparam) {
if (typeof testparam === 'undefined') return;
if (testparam) {
return true;
}
else {
return false;
}
};
var thefirst = myfunc(true)
var thesecond = myfunc(false);
var thelast = myfunc();
alert("type:" + typeof thefirst+" value:"+thefirst);
alert("type:" + typeof thesecond+" value:"+thesecond);
alert("type:" + typeof thelast+" value:"+thelast);
these return:
> type:boolean:true
> type:boolean:false
> type:undefined:undefined
note: null would return false in this example myfunc(null);
Changing your functions will actually alter the code because return; and return false; output different data types.
var test = function (x) {
if (!x) {
return;
}
else {
return false;
}
};
var a = test(true), b = test(false);
console.log(typeof b); // undefined
console.log(typeof a); // boolean