Can I redefine a JavaScript function from within another function? - javascript

I want to pass a function reference "go" into another function "redefineFunction", and redefine "go" inside of "redefineFunction". According to Johnathan Snook, functions are passed by reference, so I don't understand why go() does not get redefined when I pass it into redefineFunction(). Is there something that I am missing?
// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction(fn) {
fn = function(x) { return x * 3; };
}
// initial version of go()
function go(x) {
return x;
}
go(5); // returns 5
// redefine go()
go = function(x) {
return x * 2;
}
go(5); // returns 10
// redefine go() using redefineFunction()
redefineFunction(go);
go(5); // still returns 10, I want it to return 15
​
Or see my fiddle http://jsfiddle.net/q9Kft/

Pedants will tell you that JavaScript is pure pass-by-value, but I think that only clouds the issue since the value passed (when passing objects) is a reference to that object. Thus, when you modify an object's properties, you're modifying the original object, but if you replace the variable altogether, you're essentially giving up your reference to the original object.
If you're trying to redefine a function in the global scope: (which is a bad thing; you generally shouldn't have global functions)
function redefineFunction(fn) {
window[fn] = function() { ... };
}
redefineFunction('go');
Otherwise, you'll have to return the new function and assign on the calling side.
function makeNewFunction() {
return function() { ... };
}
go = makeNewFunction();

Nothing is "passed by reference" in JS. There are times that references are passed, but they're passed by value. The difference is subtle, but important -- for one thing, it means that while you can manipulate a referenced object pretty much at will, you can't reliably replace the object (read: alter the reference itself) in any way the caller will see (because the reference was passed by value, and is thus merely a copy of the original reference; attempting to reassign it breaks in the same way it would if the arg were a number or string).
Some cowboys will assume you're redefining a global function and mess with it by name to get around the limitations of pass-by-value, but that will cause issues the second you decide not to have globals all over the place.
The real solution: return the new function, and let the caller decide what to do with it. (I'd argue that redefining functions right out from under the code that uses them is a pretty bad design decision anyway, but eh. I guess there could be a reason for it...)

Snook is wrong. And I don't think it's pedantic at all (#josh3736 :) to point out that EVERYTHING in JavaScript is pass by value. The article by Snook gets this COMPLETELY wrong. Passing a primitive and passing an object work the exact same way. These are equivalent:
var x = 2;
var y = x;
y = 3; //x is STILL 2.
function stuff(y){
y = 3; //guess what. x is STILL 2
}
stuff(x);
///////////////////
var x = {stuff: 2};
var y = x;
y = {stuff: 3}; //x.stuff is STILL 2
function stuff(y){
y = {stuff: 3}; //guess what. x.stuff is STILL 2
}
stuff(x);
This is important. Java, C#, and MOST languages work this way. That's why C# has a "ref" keyword for when you really do want to pass something by reference.

You can't modify the variable from inside the function, so the quick fix is to return the value and assign it outside the function, like this
// log() just writes a message to the text area
function log(message) {
$('#output').val($('#output').val() + message + "\n");
}
// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction() {
newvalue = function(x) { return x * 3; };
return newvalue;
}
// initial version of go()
function go(x) {
return x;
}
log(go(5)); // returns 5
// redefine go()
go = function(x) {
return x * 2;
}
log(go(5)); // returns 10
// redefine go() using redefineFunction()
go = redefineFunction();
log(go(5)); // returns 10, I want it to return 15

I believe functions are 'passed in by value'. If you put log(f(5)); inside your redefineFunction function it will output 15, but 10 when you call log(go(5)) afterwards.
If you change redefineFunction to return the function and then assign it to go (go = redefineFunction()) it will work as you expect.

This is equivalent to asking if you can redefine any variable by passing it as an argument to some function. No. You can reassign it by, uhh, reassigning it. In this case, if you make redefineFunction return a function, you can simply assign it to go:
function redefineFunction() {
var fn = function(x) { return x * e; };
return fn;
}
function go(x) {
return x;
}
go = redefineFunction();
go(5); // return 15

This is working in firefox:
function redefineFunction(fn) {
window[fn] = function(x) {
return x * 3;
}
};
function go(x) {
return x;
};
alert(go(5));
go=function(x) {
return x * 2;
}
alert(go(5));
redefineFunction('go');
alert(go(5));
The secret is that a global function called go also is called window.go and window["go"].
This can also be used at styles: element.style["overflow"] = "hidden", and in attributes:
element["value"] = "hello there".
This is a very useful knowlege.

Why dont use a object? something like this:
var o = {
go: function( x ) {
return x;
},
redefineFunction: function ( fn ) {
if (typeof fn === 'function') {
this.go = fn;
}
}
}
console.log(o.go(5)); // return 5
var fn = function (x) {
return x * 2;
};
o.redefineFunction(fn);
console.log(o.go(5));​ //return 10
Hope it helps!

Related

Access local variable of function inside callback

If I create a callback within a function, can I get that callback to access the local variables within that function?
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc;
callback();
}
Obj.prototype.innerFunc = function()
{
x++;
}
x naturally is not within the scope of innerFunc and will produce an error if called by itself. But if I call it from outerFunc can I extend innerFunc's scope in order to access x?
Edit: Should've mentioned that I don't want to pass arguments into the function or make x and instance of Obj. I'm more looking to treat innerFunc as though it was declared locally in outerFunc. Similar to what can be done below:
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = function() {
x++;
}
callback(); // works
}
Yes: this is exactly what function parameters are for. They allow you to pass a value from one scope into another.
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc;
x = callback(x);
}
Obj.prototype.innerFunc = function(x)
{
x++;
return x;
}
Note that the value is sent to the other function, not the variable. So you need to return the value and assign it in order to use it.
If you're using prototypes, just set an instance property:
// constructor
var Obj = function () {}
Obj.prototype.outerFunc = function()
{
this.x = 0;
var callback = this.innerFunc.bind(this);
callback();
}
Obj.prototype.innerFunc = function()
{
this.x++;
}
var instance = new Obj()
instance.outerFunc()
console.log(instance.x) // returns 1
Edit: But #lonesomeday's answer is a much better solution as it takes a more functional approach avoiding side effects :)
The preffered way of doing this is to assign x to the scope of the object then all functions can access it, via this.x
Obj.prototype.outerFunc = function()
{
this.x= 0; // set x to zero
this.innerFunc();
}
Obj.prototype.innerFunc = function(x)
{
this.x++;
return this.x;
}
This is a bit hard to solve without knowing why you don't want to pass a parameter; if you just want to have a specific function signature, maybe a higher-order function might help?
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc(x);
callback();
}
Obj.prototype.innerFunc = function(x)
{
return function () { /* use x in here */ };
}
This way you have two functions one inside the other. The outer one takes the parameter, and the inner one can access the variable that is passed to the outer one.
This of course only gives you half of what you demonstrate in your example: You can access the local variable but not modify it.
You can never access any function's internal variables from outside the function under any circumstances, in an OOP context or otherwise.
The only sort-of-exception is that a function A defined inside a function B, and returned from that function B, continues to have access to the variables in function B--the basic notion of closure.
I have no idea why you don't want to use instance variables. That's what they're for--sharing data across methods. I have no idea why you don't want to pass values in or out--that's what parameters and return values are for.
can I extend innerFunc's scope in order to access x?
No, you can't, whatever that means. There is no such notion in JS.
The closest you can come to what you seem to maybe want to do is to define the variable in the constructor:
function Obj() {
var x = 0;
this.outerFunc = function() {
var callback = this.innerFunc;
callback();
};
this.innerFunc = function() {
x++;
}
}
However, this will not work as-is because this.innerFunc is missing its context. Therefore, you would need to write
var callback = () => this.innerFunc();
However, it's a mystery why you would want to do this instead of just writing this.innerFunc().

JavaScript closures for encapsulating data can be circumvented?

I always thought of JavaScript closures as a perfect way for encapsulating data, sort of making variables private. But I recently realized that this pattern is very easily broken by exploiting reference semantics:
function creator() {
var x = {
key: 3
};
return function() {
return x;
}
}
var instance = creator();
var y = instance();
y.key = 4;
//returns 4
//y is a refernce to x
console.log( instance() );
How do I make sure that the private part (variables defined in scope of creator() cannot be mutated from outside?
You should use getters and setters . Following MDN example you should be able to return the same value even if set differently:
function creator() {
var x = {
get key() {
return 4;
},
set key(x) {
// do nothing
}
};
return function() {
return x;
}
}
This way when you set key, the setter drops the input value and keeps the original init value.

Expression contains parentheses only. Function argument after } [duplicate]

This question already has answers here:
What is the (function() { } )() construct in JavaScript?
(28 answers)
Closed 9 years ago.
I got so confused here. Can someone help me peel the layers off the function definition here? What are the out-most parentheses for? Why argument (p) can be after }, and which function is it for? Where is q required at all? Why can p directly call publish() later?
var p = {};
(function(q) {
q.publish = function(topic, data){
...
};
}(p));
...
p.publish("inbox", "hello");
It simply creates the function and executes it immediately.
For example:
var foo = function() {
return 5;
}();
console.log(foo);
will print 5.
If you want to learn more about it, please read this excellent article http://benalman.com/news/2010/11/immediately-invoked-function-expression/
I would like to quote module pattern example from the link I shared.
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function( val ){
i = val;
},
increment: function() {
return ++i;
}
};
}());
console.log(counter.get());
counter.set(3);
console.log(counter.increment());
console.log(counter.i);
Output
0
4
undefined
Here we are dynamically creating an Object at the same time we are making i private. This is called closure property.
Putting the function in parentheses means the JS interpreter takes it as a function expression, so it can be anonymous (i.e., not have a declared name). Adding () at the end means the function is called immediately. So, e.g.:
(function() {
alert('Hi');
}());
...declares a really simple function with no arguments, and calls it immediately. A slightly more complicated one with an argument might look like this:
(function(someArgument) {
alert(someArgument);
}('Hi'));
That would alert 'Hi', because the string 'Hi' is passed to the anonymous function when it is called.
So with that as background, here's what your code is doing line by line:
var p = {}; // declare variable p, referencing an empty object
(function(q) { // make an anonymous function expression that takes one argument, q
q.publish = function(topic, data){ // add a property 'publish' to whatever q is,
... // where 'publish' is a function that takes
}; // two arguments
}(p)); // call the anonymous function, passing p in
...
p.publish("inbox", "hello"); // call the method 'publish' that was added to p
The q argument that you asked about takes the value from p, so it refers to the same empty object, but then it adds the .publish() method to that object.
This general concept is called an "Immediated invoked function expression", or IIFE.
Usually if an IIFE is just sitting there by itself like that (i.e., another variable is not assigned equal to it) it is done so that working variables/functions can be created temporarily without adding them to the global scope, because in JavaScript the scope options are basically global or function. The code you show doesn't do that, but here's a simple example:
(function() {
var x = 0;
for (var i = 0; i < 100; i++)
x += i;
alert (x);
}());
// here x and i are not accessible because they're local to the function above.
It's a self executing function. Using q is useless here since q === p.
var p = 'hello';
function f(q){ return q; }; f(p); // "hello"
(function(q){ return q; }(p)); // "hello"
(function(){ return p; }()); // "hello"
/*(*/function(){ return p; }()/*)*/; // SyntaxError: Unexpected token (
This pattern is usually used to create a private context for variables. Here is a well known example :
var counter = function(){
var i = 0;
return function(){
return ++i;
};
}();
counter(); // 1
counter(); // 2
i; // undefined
Have a look at this great article : http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html.

Javascript anonymous function use-case

I am working my way through Eloquent Javascript and I came across a code snippet that looks like this:
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
show(greaterThanTen(9));
Is there any real use-case to defining the function like this with an anonymous function inside of it? Wouldn't it be much simpler to do this:
function greaterThan(x,y){
return x > y;
}
var greaterThanTen = greaterThan(9, 10);
any ideas/comments/suggestions would be very helpful.
This is an example of a "closure". Basically, a call to greaterThan() gives you a function. That function, instead of just a mere function, carries with it the value of x - it's like embedding the value of x permanently into the function.
function obj(x) {
//"public interface"
//only these are exposed (inc and getX). x is private.
return {
inc: function() {
return ++x;
},
getX: function() { //a getter function to retrieve private x
return x;
}
}
}
//the value 10 is "embedded" to the returned object
var myobj = obj(10);
//every call to inc increments that "embedded" value
console.log(myobj.inc()); //11
console.log(myobj.inc()); //12
console.log(myobj.inc()); //13
//but you can never access the variable of `x` directly without a "getter"
console.log(myobj.getX());​
Closures are one of the great features of JavaScript. One of it's great uses is to emulate private variables.
The first example you are combining functions.
Of course you can write in different ways but the idea of greaterThanTen in the first example is be something different. For example you can pass this to a filter
var a = [ 1 , 10, 100 , 9, 43 ];
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
a.filter(greaterThanTen);
returns [100, 43]
It is functional programming. There is many advantages.
Unless I missed something, the first code returns a function.
The second one returns the result.
That's not a particularly good use case. A better use case for anonymous functions is callbacks, as in: you wish to execute function #2 once function #1 is completed.
function a(param1, param2, callback) {
//work on param1 and param2 here
callback.call(); //triggers the callback function
}

how to use function(1)(2) in javascript? and how does it work?

I understand calling function(1) but not function(1)(2), how does it work?
also possible for function(1)(2)(3)(4) too?
In this case you are supposing that function(1) returns a function, than you are calling this new, anonymous function with an argument of 2.
See this example:
function sum(a) {
return function(b) {
return a+b;
}
}
// Usage:
window.alert(sum(5)(3)); // shows 8
var add2 = sum(2);
window.alert(add2(5)); // shows 7
window.alert(typeof(add2)); // shows 'function'
Here we create a function sum that takes one argument. Inside the function sum, we create an anonymous function that takes another argument. This anonymous function is returned as the result of executing sum.
Note that this anonymous function is a great example of what we call closure. A closure is a function that keeps the context in which it was created. In this case, it will keep the value of the variable a inside it, as did the example function add2. If we create many closures, they are independent as you can see:
var add3 = sum(3);
var add4 = sum(4);
window.alert(add3(3)); // shows 6
window.alert(add4(3)); // shows 7
Furthermore, they won't get "confused" if you have similarly named local variables:
var a = "Hello, world";
function multiply(a) {
return function(b) {
return a * b;
}
}
window.alert(multiply(6)(7)); // shows 42
var twoTimes = multiply(2);
window.alert(typeof(twoTimes));
window.alert(twoTimes(5));
So, after a call to sum(2) or multiply(2) the result is not a number, nor a string, but is a function. This is a characteristic of functional languages -- languages in which functions can be passed as parameters and returned as results of other functions.
You have a function that returns a function:
function f(n) {
return function(x) {
return n + x;
};
}
When you call f(1) you get a reference to a function back. You can either store the reference in a variable and call it:
var fx = f(1);
var result = fx(2);
Or you can call it directly:
var result = f(1)(2);
To get a function that returns a function that returns a function that returns a function, you just have to repeat the process:
function f(n) {
return function(x) {
return function(y) {
return function(z) {
return n + x + y + z;
}
}
};
}
If your function returns a function, you can call that too.
x = f(1)(2)
is equivalent to:
f2 = f(1)
x = f2(2)
The parenthesis indicate invocation of a function (you "call" it). If you have
<anything>()
It means that the value of anything is a callable value. Imagine the following function:
function add(n1) {
return function add_second(n2) {
return n1+n2
}
}
You can then invoke it as add(1)(2) which would equal 3. You can naturally extend this as much as you want.

Categories