I need to check if a javascript function has been modified by someone overwriting its prototype, or some other way.
For example:
var calc = function(x,y) { return x * y; }
How can I get the code for calc (function(x,y) { return x * y; }) and save it as a string.
I tried:
calc.prototype.toString
calc.toString
But that seems to do something entirely different, it always returns:
toString() { [native code] }
Function.prototype.toString is a function, you're looking at the code of toString rather than your function:
calc.toString()
Is what you're looking for.
Related
I have a script like this:
function changeValue(x){
x = 30;
}
let a = 3;
changeValue(a);
console.log(a);
The above code outputs 3, but the expected output is 30. Now I'm aware why this is happening, but how do I modify my code so that the changes made do not revert after the changeValue function ends?
I have read that there are no explicit pointers in JS and I don't want to alter the value using the global variable name or by using the object approach. Is there any other way to solve the problem?
Thank you
The best way would be to use return, because x isn't an object, it's just a variable. It is discarded after the function.
Using Return:
function changeValue(x){
return 30;
}
let a = changeValue(3);
changeValue(a);
console.log("Output Is:", a);
In JavaScript, all primitive types (integers, floats, etc) are passed by value, so as other people said, for your specific use case, it's better to return the value like this:
function returnValue(x) {
return x * 10
}
let a = 3;
a = returnValue(a);
console.log(a);
However, if you really want to change the argument and NOT return, you need to do it with pass by reference. As I said above, it's not possible with primitive data types but is possible with objects:
function changeValue(x) {
x.value = x.value * 10;
}
let a = { value: 3 };
changeValue(a);
console.log(a.value);
Let's look at those examples:
var a = 1;
var b = { toString:function() {return '1'} };
var c = 1;
a + b + c === "111" // true
It is pretty mind blowing. I know that JS interpreter performs ToPrimitive or ToString operations when we use + operator. But why is object b gets converted to a string when there is no hint PreferredType. Thus it is probably using ToString operation.
Another note: it is only gets converted to string if there is toString method exists on object, why? And if I call that method "toNumber", why it is not converted to number?
Why JavaScript behaves like that?
But why is object b gets converted to a string when there is no hint PreferredType.
When no hint is passed, then the object's valueOf method will be called first. But since b.valueOf() doesn't return a primitive value (it returns the object itself by default), b.toString() will be called next.
See the specification.
The conversion rule can be summarized as follows:
If there is no hint or hint is number, call valueOf first.
If hint is string, call toString first.
If the return value is not is not a primitive value, call the other method.
If the return value is still not a primitve, throw an error.
it is only gets converted to string if there is toString method exists on object, why?
Not sure I understand this statement. Every object has a toString method. If you try to perform this operation on an object without a toString method (via Object.create(null)), an error is thrown.
And if I call that method "toNumber", why it is not converted to number?
Because toNumber has no meaning in JavaScript. toString and valueOf are the two "magic" methods via which objects are converted to primitive:
var n = 1;
var o = {
toString() { return 'bar'; },
valueOf() { return 2; }
};
console.log(n + o);
console.log(String(o));
If none of the methods return a primitive, you would get an error as well.
var n = 1;
var o = {
toString() { return this; },
};
console.log(n + o);
These two methods and their naming seems kind of arbitrary. From ES6 on, the preferred way to define a conversion function is to use the well-known ##toPrimitive symbol:
var a = 1;
var b = { [Symbol.toPrimitive]: function() {return 1} };
var c = 1;
console.log(a + b + c);
##toPrimitive is called before valueOf or toString are called.
Why JavaScript behaves like that?
Because that's how it is defined in the specification. If you want to know the rationale behind that, you have to ask the people who made that decision.
I have so far:
function func(f,x) {
alert(f(x));
}
func(function(x) {return x*x;},2);
This works, but i am thinking that passing function(x) {return x*x;}, is excessive and I could just pass x*x, as the idea is that I can supply (pretty much) any function.
I have tried:
function func(f,y) {
g=function() {return f;};
alert(g(y));
}
func(x*x,2);
amongst others, but I can't get it to work. Perhaps if I passed 'x*x' as a string..?
You're correct that the syntax is excessive, but for ES5 and before, that's just how it is.
However, in ES6 you can use the new "arrow function" lambda syntax:
func(x => x * x, 2);
See http://www.es6fiddle.net/i4o5uj2l/
FWIW, the above func isn't great since it only supports unary functions, i.e. those taking a single parameter. You could expand func to use ES6 "spread arguments":
function func(f, ...args) {
console.log(f.apply(this, args));
}
func((x, y) => x * y, 3, 7);
> 21
Well I have a way to do that using eval here http://jsfiddle.net/q5ayoszy/
function func(f,y) {
g=function()
{ x=y;
return eval(f);
};
alert(g(y));
}
func('x*x',2);
Note : I pass the expression as a string and then use it inside the function.
You just need to assign the value of y to the variable x inside the function so the eval evaluates correctly
The only way to do that with a string is by using the infamous eval: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
var x = 2;
var y = eval("x * x"); //y = 4
But using eval is almost always a very bad idea.
You could use currying to break down the process into smaller functions:
function multiply(x) {
return function() {
return x*x;
}
}
var bytwo = multiply(2);
bytwo(); // 4
js named function in parameter, can not access out of function
Because the 5th edition of ECMAScript forbids use of arguments.callee() in strict mode.
mdn warning
So I decided do not use the callee, instead , I use a named function
The example in mdn
function factorial (n) {
return !(n > 1) ? 1 : factorial(n - 1) * n;
}
[1,2,3,4,5].map(factorial);
become:
[1,2,3,4,5].map(function factorial(n) {
return !(n > 1) ? 1 : /* what goes here? */ factorial(n - 1) * n;
});
This is a good idea, but I want to reuse the function factorial
DEMO
function d(x){return x;}
d(function a(){});
d(a);// this is not work, a is undefined(works in ie, failed in ff and chrome)
This is bother me, as I know, the scope in js is function-level, why the second a is undefined ?
jsfiddle DEMO
You're really asking two questions here. The first is easy:
[1,2,3,4,5].map(function factorial(n) {
return !(n > 1) ? 1 : /* what goes here? */ factorial(n - 1) * n;
});
What you've got there works just fine. In other words, since you're naming your function (factorial), that identifier is available inside the function body, enabling recursion.
Your second question is a little trickier:
function d(x){return x;}
d(function a(){});
d(a);// this is not work, a is undefined(works in ie, failed in ff and chrome)
It is correct for a to be undefined. If you read the ECMAScript specification, section 13.2.1 clearly states that new execution context that's created includes the actual parameters (argument list). That is, a is defined within the execution context of d, not the caller. It looks like IE is expressing erroneous behavior.
The name of a function expression does not reference itself in the namespace it's defined in (IE bugs on this) but does reference itself within itself
[1].map(function foo() {return foo;});
// [function foo() {return foo;}]
foo;
// undefined
If you want a reference to the function so it can be re-used, create a reference to it, either go back to writing a function declaration (function as a statement), or set the function expression as a variable, and pass the variable as desired
var bar = function foo() {return foo;};
[1].map(bar);
// [function foo() {return foo;}]
foo;
// undefined
bar;
// function foo() {return foo;}
Note that inside the function named foo in this example, both foo and bar will point to the same function, unless bar is changed again later.
var bar = function foo() {return foo === bar;};
bar(); // true, bar is foo inside the function
// change value of bar, keep a reference to function foo
var temp = bar;
bar = 'something else';
temp(); // false, bar is no longer foo inside the function
You say that your previous example doesn't work, but I have to disagree with you,
[1,2,3,4,5].map(function factorial(n) {
return n == 0 ? 1 : factorial(n - 1) * n;
});
I tried this (yes I modified it a bit) using basic logging and it logged n-1 for every recursion indicating that the recursion works fine. I believe Paul explains just fine why.
I recommend, anyway, to change the way you're thinking here because imagine if you're finding factorial(100). You'd be doing
... * factorial(98 - 1) * 98 * 99 * 100
Imagine the overload. I recommend adding a optional parameter which is the sum of the currently evaluated factorials, your result is the same but the overload is way less.
[1,2,3,4,5].map(function factorial(n, sum) {
var sum = sum || 1;
return n == 0 ? 1 : factorial(n - 1, sum*n);
});
I just bought the newest version of "JavaScript: The Definitive Guide" and already have a question. :D
Are the following lines semantically the same:
var square = function(n){
return n * n;
};
and
function square(n){
return n * n;
}
If yes, what are the advantages/disadvantages of using either of them?
Thanks for your help!
Check this out:
a(); // prints 'A'
function a(){
console.log('A');
};
and this:
b(); // throws error. b is not a function
var b = function() {
console.log('B');
};
Did you notice the difference?
Yes, they do the exact same thing.
The main advantage of the first approach is that it gives you a reference to that function so that you could pass it to another function or attach it to an object if you need to.
Difference is that in the first solution, you can do that :
var square = function(n){
return n * n;
};
// some code
square = function(n) { return n*n*n; }
you have reference to a function. On the other solution, the function is statically declared.
Disclaimer: need JS guru to tell me if I'm wrong =).