How to monkey-patch a function declared inside another function - javascript

Say I have the following code:
window.foo = function() {
bar();
function bar() {
console.log('hello');
}
}
/* insert monkey-patching code here */
foo();
What code can I replace /* insert monkey-patching code here */ with in order to make this e.g. write goodbye instead of hello on the console?
I have tried the following in order to override bar, but it does not work:
window.foo = function() {
bar();
function bar() {
console.log('hello');
}
}
window.bar = function() {
console.log('goodbye');
}
window.foo.bar = function() {
console.log('goodbye');
}
foo();

You can't.
The function is stored in a local variable inside foo. It isn't accessible from outside that function.
You would need to either:
Replace the whole of foo
Refactor foo so bar was declared in a wider scope (and accessible from where you want to change it)

Related

new Function scope

I've got a piece of code with a ReferenceError here
or below:
function foo() {
function bar() {
console.log('bar');
}
var x = new Function('bar();');
x();
}
foo(); // ReferenceError: bar is not defined
Is it possible to make this happen? I mean the bar function to exist inside the new Function
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called.
— MDN
So no, it isn't while using that approach.
Don't use the function constructor. It is inefficient, and converting strings to code is fraught with problems.
function foo() {
function bar() {
alert('bar');
}
function x() {
bar();
}
x();
}
foo();
One possible approach is to use eval instead of new Function:
function foo() {
function bar() {
console.log('bar');
}
eval('x = function() { bar(); }');
x();
}
foo(); // works fine.

function statement and function expression inside if statement

Any reason why the following snippet shows different output in Firefox and Chrome:
var sayHo;
console.log(typeof(sayHey));
console.log(typeof(sayHo));
if(true) {
function sayHey() {
console.log("Hey, inside if");
};
sayHo = function() {
console.log("Ho, inside if");
};
}
else {
function sayHey() {
console.log("Hey, inside else");
};
sayHo = function() {
console.log("Ho, inside else");
};
}
sayHey();
sayHo();
Chrome(v31) outputs
function
undefined
Hey, inside else
Ho, inside if
Firefox(v26) outputs
undefined
undefined
Hey, inside if
Ho, inside if
I expected the same output what Chrome gave. During parse time, the function declaration inside will override the function declaration inside if. Because JavaScript will try to hoist both the function declarations, hence the override.
Firefox and Chrome use different JavaScript engines (SpiderMonkey and V8 respectively). The Chrome behaviour can be considered either a 'bug' or an 'ease of use feature'. In V8 function definitions inside if statements (rather than assignment of an anonymous function to a variable) are performed pre-execution. It's a design decision.
It all boils down to hoisting differences :
Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:
function foo() {
bar();
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
bar();
x = 1;
}
Consider this example :
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
this code is equivalent to :
function test() {
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
}
test();
Look what happened to the function declaration : it is hoisted.
Leet's look at simplier sample : http://jsbin.com/UKICENE/4/edit
console.log(typeof(sayHey));
if(true) {
function sayHey() {
console.log("Hey, inside if");
};}
sayHey();
This will yield function in chrome.
But it will yield undefined in FF.
Hoeever - deferring the calculationm via setTimeout will yield the same result as chrome :
console.log(typeof(sayHey));//undefined
setTimeout(function (){console.log(typeof(sayHey));},1000); //function
if(true) {
function sayHey() {
console.log("Hey, inside if");
};}
sayHey();
So , like Šime said , it delay the evaluation.
If you ask me , I think chrome is doing the right thing

Is it possible to identify in the function-constructor what object calls it and abort creation if the wrong object calls?

I have function-constructor. I want to control what function (object) can call it. Here'e the example:
function Bar() {
// foo can be created only here, when Bar is instantiated
var foo = new Foo();
}
function Foo() {
// I'd like to have something like this here:
if (caller != Bar) {
alert("Not allowed, the caller is not Bar");
return;
}
}
var bar = new Bar(); // this is correct, Foo can be created inside Bar
var foo = new Foo(); // prints "Not allowed, the caller is not Bar" and exits
Is it possible to implement in JS? Are there some functions for such kind of control?
What will be created from Foo if the creation will be aborted this way?
You can't reliably identify the caller in a constructor across browsers, particularly in the new strict mode.
Instead, you can define Foo() inside of Bar() or define them both inside of the same self executing function so that Foo() is not known outside the scope of Bar() and can thus only be created there.
Some examples:
// Bar() is only known within a single scope
var Foo;
(function(){
Foo = function() {
}
function Bar() {
}
})();
// Bar() is only known inside of Foo()'s constructor
function Foo() {
function Bar() {
}
}
You may find this article instructional which discusses various ways of making instance data truly private: http://www.crockford.com/javascript/private.html. It's not exactly the same as what you're asking here, but uses some of the same techniques (hiding private data in a closure).
You can try something like: (don't think this is cross browser solution however)
var caller = Foo.caller.name;
if (caller != "Bar") {
}
See this answer for more details.
Another option is to have a global variable that is false by default and you assign to true in the functions you want to allow and to a check in that function.
If you want to restrict the creation of the Foo object within Bar, then you can define the function with in Bar.
e.g:
function Bar() {
var Foo = function Foo() {
// I'd like to have something like this here:
if (caller != Bar) {
alert("Not allowed, the caller is not Bar");
return;
}
}
var foo = new Foo();
.
.
.
.
}
Now Foo is not visible outside the Bar scope.
You could simply not expose Foo:
(function() {
function Bar() {
var foo = new Foo();
}
function Foo() {
}
window.Bar = Bar; //Expose bar to global scope
})();
A function, when called as constructor returns the created object unless you explicitly return a non-primitive value. So having return; would still return the created object.

Function Objection Notation?

I was wondering whether there is any performance / advantage of writing javascript in this format ?
var myFuncs = {
var firstFun = function() {
// do something
},
var secondFunc = function() {
// do something
},
var thirdFunc = function() {
// do something
}
}
So they can be called like
myFuncs.firstFun();
I'm trying to understand how this is more advantageous [other than code readability] ?
Function vs Object declaration
You can't use that particular syntax, the correct form is:
var myFuncs = {
firstFn: function () {},
secondFn: function () {},
...
};
The advantage to writing functions within an object has to do with namespacing and context. If you wrote:
var firstFn = function () {};
-or-
function firstFn() {}
the function would be defined at window.firstFn. Adding the functions on myFuncs makes the functions accessible at window.myFuncs.firstFn. If you want your JavaScript to work with other scripts you wouldn't want to have your foo function conflict with someone elses foo function:
<script src="a.js">
function foo() {...}
</script>
<script src="b.js">
function foo() {...} //this script would overwrite the foo function in a.js
</script>
<script src="c.js">
var bar = { //this script would be accessed at bar.foo()
foo: function () {..}
}
</script>
The calling context (this) of the function will also be different:
function foo() {
console.log(this); //window
}
var bar = {
foo: function () {
console.log(this); //bar object
}
}
Closure Syntax
What you may be getting confused with is the syntax for declaring functions within a closure:
(function () {
var foo = function () {...};
foo();
}());
In this case the closure is used to prevent the function from polluting the global scope (window.foo will not be set). This allows multiple scripts to use the same function names without worrying about being overridden.
OOP Syntax
The object syntax is often used to define the prototype for a JavaScript "constructor". In JS all functions can be called as a constructor simply by using the new keyword when the function is called:
function foo() {...}
var f = new foo(); //don't do it this way
For readability/maintainability/consistency you should always name your constructor using PascalCase:
function Foo() {...} //tells other developers this is a constructor
function bar() {...} //tells other developers this is a function
var f = new Foo();
var b = bar();
Without getting too lost in the details of how prototype works, you can assign methods to be shared across every instantiated object of a function by assigning an object to the function's prototype property:
function Foo() {...}
Foo.prototype = { //note the use of the object declaration for the functions
bar: function () {...},
baz: function () {...},
...
};
var f = new Foo();
f.bar(); //calls the bar function that was defined in the prototype
I think what you're asking is for advantages between declaring all of your functions globally, vs putting them all into an object. There is no performance difference. The main reason why people generally suggest adding them all into an object is to not clutter up the global space.
Think about it this way. If you create a global function named init in a javascript library, and make it global. Then if someone else does the same, it will overwrite your init. But, if you put it in an object named someJSLibrary, the odds of some other code overwriting your functions are much less.

When to use anonymous JavaScript functions?

I'm trying to understand when to use anonymous JavaScript functions.
State differences between the functions? Explain when you would use each.
var test1 = function(){
$("<div />").html("test1").appendTo(body)
};
function test2() {
$("<div />").html("test2").appendTo(body)
}
I think the answer is that one uses anonymous function and the other doesn't to replace an empty div element. Does that seem right?
In your example it really doesn't make a huge difference. The only difference is that functions declared using function foo() { } are accessible anywhere within the same scope at any time, while functions declared using var foo = function () { } are only accessible after the code that does the assignment has run.
foo(); // ok
function foo() { ... };
bar(); // error, bar is not a function
var bar = function () { ... };
bar(); // ok
You usually use anonymous functions in cases where you don't need a named function, or where you're constructing objects:
arr.sort(function (a, b) { return a - b; }); // anonymous callback function
function MyObject() {
this.foo = function () { ... } // object constructor
}
You would use a function like the following (which is another type of anonymous function) when you do not want to pollute the global namespace:
(function() {
var pollution = 'blablabla';
function stinky() {
// Some code
}
})();
You may check John Resig's Secrets of JavaScript Libraries, especially page 47 for JavaScript function. Quite lengthy, but you'll learn more about JavaScript

Categories

Resources