Consequences of Dynamically rewriting a function in javascript? - javascript

In javascript, you can rewrite a function, like so:
function foo() {
setTimeout(function() {
alert('sup stallion');
foo = function() { //rewrite foo to nolonger wait 4 seconds to alert.
alert('sup stallion');
}
}, 4000);
}
Obviously this is a contrived example, but is there anything conceptually wrong with this approach (other than a race condition).

Self modifying code can be confusing, and hard to debug, so it's generally avoided.
Other than that there is no problem, and no race condition either.

One thing I noticed while testing your code. Consider this:
setInterval(foo, 6000);
Function foo is being passed to setInterval before it was modified, and the original foo will run every 6 seconds, even after the binding has been updated.
On the other hand, the code below will run the original function only on the first call (which updates the binding). Subsequent calls will invoke the updated version:
setInterval(function(){foo();}, 6000);
Looks obvious, but could be hard to debug...

Dynamic function rewriting can be used as a form of lazy initialization, however there is a catch:
function Foo() {...}
Foo.prototype = {
bar: function () {
//some initialized variables to close over
var a, b, c, ...;
Foo.prototype.bar = function () {
//do stuff with variables
};
Foo.prototype.bar.call(this);
}
};
While this code is relatively straight-forward to understand, and would be used as:
var f = new Foo();
f.bar(); //initializes `bar` function
f.bar(); //uses initialized `bar` function
it has a hidden issue:
var f = new Foo(),
g = {};
//passing by reference before the function was initialized will behave poorly
g.bar = f.bar;
f.bar(); //initializes `bar` function
g.bar(); //re-initializes `bar` function
f.bar(); //uses initialized `bar` function
g.bar(); //re-initializes `bar` function
It's for this reason that any initialization needed for a function is typically done using a module pattern:
function Foo() {...}
Foo.prototype = {
bar: (function () {
var a, b, c, ..., fn;
//some initialized variables to close over
fn = function () {
//do stuff with variables
};
return fn;
}())
};
The module pattern has the disadvantage of calling the initialization code immediately, but wont have the issues associated with the function reference.

Related

JavaScript setInterval not being properly bound to correct closure

Problem
Hi people, I'm reasonably new to JavaScript and I come from the very object-oriented world of Python and Java, that's my disclaimer.
There are two chunks of code below, alternative implementations, one in JavaScript, one in Coffeescript. I am trying to run them on the server in a Meteor.js application. The problem I am experiencing is when calling the function "setInterval" using the bound-method "this.printSomething" as my callback, once that callback is executed, it loses scope with the instance resulting in "this.bar" being undefined! Can anyone explain to me why either the JavaScript or the coffescript code isn't working?
JavaScript Implementation
function Foo(bar) {
this.bar = bar;
this.start = function () {
setInterval(this.printSomething, 3000);
}
this.printSomething = function() {
console.log(this.bar);
}
}
f = new Foo(5);
f.start();
Coffeescript Implementation
class foo
constructor: (bar) ->
#bar = bar
start: () ->
Meteor.setInterval(#printSomething, 3000)
printSomething: () ->
console.log #bar
x = new foo 0
x.start()
You lose your context of Foo in the setInterval callback. You can use Function.bind to set the context to something like this to set the context for the callback function reference back to Foo instance.
setInterval(this.printSomething.bind(this), 3000);
With the call
setInterval(this.printSomething, 3000);
The callback method gets the global context (window in case of web or global in case of tenants like node) so you don't get property bar there since this refers to the global context.
Fiddle
or just
this.printSomething = function() {
console.log(bar); //you can access bar here since it is not bound to the instance of Foo
}
You could also try creating a closure to capture the this. Like this:
var self = this;
this.start = function () {
setInterval(function(){
self.printSomething();
}, 3000);
}
When you enter a function, you get a new scope in javascript. You can inherit from the parent scope, but the value of this changes. In coffeescript, you can use the fat arrow (which looks like it is going to be part of ecmascript 6) which basically retains a reference to this before going into the new scope.
class foo
constructor: (bar) ->
#bar = bar
start: () =>
Meteor.setInterval(#printSomething, 3000)
printSomething: () =>
console.log #bar
x = new foo 0
x.start()
The standard way to handle this kind of thing in javascript is to create a reference to this at the point you want to refer to, and then use the reference in your out of scope calls...
function Foo(bar) {
// make reference to `this` at the point
// where you want to use it from
self = this;
self.bar = bar;
self.start = function () {
setInterval(self.printSomething, 3000);
}
self.printSomething = function() {
console.log(self.bar);
}
}
f = new Foo(5);
f.start();

Accessing properties of a function inside different levels of its "prototype" functions -- and -- recursive functions

Ok, this has been confusing me for days! Let's say I have something like:
var FooBar = function(args) {
this.annoy = typeof args == "boolean" ? args : false;
this.Foo();
}
FooBar.prototype.Foo = function() {
if (this.annoy)
window.alert("My name is Foo!")
else
window.console.log("My name is Foo!")
this.Bar()
}
FooBar.prototype.Bar = function() {
if (this.annoy)
window.alert("My name is Bar!")
else
window.console.log("My name is Bar!")
}
This works fine. However, what if Bar() was defined as a property of another object which is further a property of FooBar's prototype, is there a way to access annoy in the new Bar() without having to pass annoy as an argument to it? For example:
FooBar.prototype.evenDeeper = {
Bar: function() {
// I wish to access "annoy" here!
},
anotherOne: function() {
},
yetAnotherOne: 'value'
}
I might be wrong but I am sure that inside Foo(), Bar() would be referred to as this.evenDeeper.Bar(), wouldn't it? Moreover, what if Bar() wanted to be recursive? Would Bar() just refer to itself as Bar() inside itself, or as Foobar.evenDeeper.Bar() or this.Bar() or what?
Summary
How can Bar() access annoy if it's inside evenDeeper?
How does Bar() refer to itself within itself?
Disclaimer: I am not even remotely planning on annoying anyone with alert()s! ;)
1.
A) pass a variable to evenDeeper.Bar;
B) use evenDeeper.bar.apply(new FooBar(args)) to access FooBar prototype using 'this';
C) assign evenDeeper.annoy the FooBar.annoy variable (not recommended because booleans are passed by value and it won't reflect changes to it)
2.
A) use this.Bar() from within evenDeeper.Bar() and it should refer to itself unless you have changed the 'this' variable.
B) pass this.Bar as a callback to this.Bar() and execute it within itself
C) declare this.Bar() in a function context so it can refer to itself as simply Bar(), example follows:
FooBar.prototype.evenDeeper = (function () {
function Bar() {
if (this.annoy) {
alert('are you annoyed yet?');
}
Bar.apply(this);
}
return {
Bar: Bar,
anotherOne: function () {},
yetAnotherOne: function () {}
};
}());
var test = new FooBar(true);
// WARNING: this will never finish!
test.evenDeeper.Bar.apply(test);
This is a generic solution, if you posted something more specific there are most likely better ways to achieve what you want. Personally, I would avoid creating a function which relies on a namespace other than the one it is in.

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.

jQuery-style function that can be accessed like an object

I am creating an AJAX API for a web service and I want to be able to call jQuery-like accessors.
jQuery seems to be able to execute 'jQuery' as a function, but also use it to directly access the object that is the result of the function EG:
jQuery();
jQuery.each({});
This is the trick that I can't seem to pull off:
myAPI('foo'); //output: 'foo'
myAPI('foo').changeBar(); //output: 'foo' 1
myAPI.changeBar(); //Error: not a function
I have seen the answers to similar questions, which are helpful, but don't really answer my question.
#8734115 - Really interesting, but you can't access the methods that were set by f.prototype.
#2953314 - Uses Multiple operations to create object instead of a single function.
here is my code:
(function(window) {
var h = function(foo) {
// The h object is actually just the init constructor 'enhanced'
return new h.fn.init(foo);
};
/**
* Methods defined at protoype.
*/
h.fn = h.prototype = {
constructor: h,
init: function(foo) {
console.log(foo);
return this;
},
splice : function () {},
length : 0,
bar : 0,
changeBar : function() {
this.bar++;
return this.bar;
}
};
h.fn.init.prototype = h.fn;
//Publish
window.myAPI =h;
}( window));
I'm sure I'm missing something simple :(
What jQuery is doing there is using jQuery as both a function and as a pseudo-namespace. That is, you can call jQuery: var divs = jQuery("div"); and you can use properties on it, e.g.: jQuery.each(...);.
This is possible because in JavaScript, functions are first-class objects, and so you can add arbitrary properties to them:
function foo() {
alert("Foo!");
}
foo.bar = function() {
alert("Bar!");
};
foo(); // "Foo!"
foo.bar(); // "Bar!"
That's literally all there is to it.
Within the call to bar, this will be the foo function (because this is determined entirely by how a function is called, not where it's defined). jQuery doesn't use this to refer to itself (usually it uses this to refer to DOM elements, sometimes to other things like array elements; when referring to itself, since it's a single thing, it just uses jQuery).
Now, you might want to ensure that your functions have proper names (whereas the function I assigned to bar above is anonymous — the property has a name, but the function does not). In that case, you might get into the module pattern:
var foo = (function() {
function foo() {
alert("Foo!");
}
function foo_bar() {
alert("Bar!");
}
foo.bar = foo_bar;
return foo;
})();
foo(); // "Foo!"
foo.bar(); // "Bar!"
That pattern also has the advantage that you can have private data and functions held within the scoping function (the big anonymous function that wraps everything else) that only your code can use.
var foo = (function() {
function foo() {
reallyPrivate("Foo!");
}
function foo_bar() {
reallyPrivate("Bar!");
}
function reallyPrivate(msg) {
alert(msg);
}
foo.bar = foo_bar;
return foo;
})();
foo(); // "Foo!"
foo.bar(); // "Bar!"
reallyPrivate("Hi"); // Error, `reallyPrivate` is undefined outside of the scoping function
In your code, you're assigning things to the prototype property of the function. That only comes into play when the function is called as a constructor function (e.g., via new). When you do that, the object created by new receives the function's prototype property as its underlying prototype. But that's a completely different thing, unrelated to what jQuery does where it's both a function and a pseudo-namespace.
You do not need any of that weirdness, to use stuff like $.each
you just attach functions to the function object instead
of the prototype object:
function Constructor() {
if (!(this instanceof Constructor)) {
return new Constructor();
}
}
Constructor.prototype = {
each: function() {
return "instance method";
}
};
Constructor.each = function() {
return "static method";
};
var a = Constructor();
a.each(); //"instance method"
Constructor.each(); //"static method"

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