Function Objection Notation? - javascript

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.

Related

JavaScript: Access 'this' when calling function stored in variable

I'm new to JavaScript so this is possibly a trivial question:
I'm trying to construct an object that stores a mapping from a set of integers to some of its methods, i.e. something like this:
'use strict';
function Foo() {
this.funcs = {
1: this.func1,
2: this.func2,
}
}
Foo.prototype.func1 = function() {
this.prop = 1;
}
Foo.prototype.func2 = function() {
this.prop = 2;
}
I'd then like to be able to call methods of Foo like this:
foo = new Foo();
var func = foo.funcs[1];
func();
But this results in: Cannot set property 'prop' of undefined, i.e. this does not refer to foo.
What's the problem here and is there a better way to implement this?
Your problem is this line:
var func = foo.funcs[1];
JavaScript determines the value of this based on how a function is called. If you use dot notation, such as foo.funcs[1](); then the value of this will associated with the foo object. But when you run func(), that's just a plain function and this will have the default value of undefined.
It would be worth your time to read the two chapters of You Don't Know JS that discuss this. It should take less than an hour to learn, and you'll be way ahead of most JS programmers once you learn it.
The rules might not make sense until you read the chapter, but they are summarized below:
Determining the this binding for an executing function requires
finding the direct call-site of that function. Once examined, four
rules can be applied to the call-site, in this order of precedence:
Called with new? Use the newly constructed object.
Called with call or apply (or bind)? Use the specified object.
Called with a context object owning the call? Use that context object.
Default: undefined in strict mode, global object otherwise.
Based on the above rules, the code below is the simplest way you could get it to work the way you are expecting it to:
'use strict';
function Foo() {
this.funcs = {
1: this.func1,
2: this.func2,
}
}
Foo.prototype.func1 = function() {
this.prop = 1;
console.log('called func1. this.prop =', this.prop);
}
Foo.prototype.func2 = function() {
this.prop = 2;
console.log('called func2. this.prop =', this.prop);
}
const foo = new Foo();
foo.funcs[1]();
There are a few ways to achieve what you require, however the most robust approach is to bind() each function to the instance of Foo() that is being instantiated.
This can be done by passing this to bind() of each function:
this.func1.bind(this)
Using bind() in this way ensures that this, for func1 and func2 is defined as the instance of Foo(). This in turn ensures that this.prop can be accessed and assigned as expected:
'use strict';
function Foo() {
this.funcs = {
/* Bind the functions to this Foo() instance */
1: this.func1.bind(this),
2: this.func2.bind(this),
}
}
Foo.prototype.func1 = function() {
this.prop = 1;
console.log('called func1. this.prop =', this.prop);
}
Foo.prototype.func2 = function() {
this.prop = 2;
console.log('called func2. this.prop =', this.prop);
}
const foo = new Foo();
var func = foo.funcs[1];
func();
foo.funcs[2]();
Another key thing to note is the bind() based approach above ensures that, if you acquire and call a reference to one of the functions on the funcs field as shown in your original post, that it will work as expected:
/* As per original post - doing this is not possible without .bind() */
var func = foo.funcs[1];
func();
Without the use of bind(), this method of acquiring and calling func will fail due to func not being bound to the instance of Foo.

Using variable as shorthand for Foo.prototype

I just started using module pattern in JavaScript to declare functional objects, but found it annoying to repeat the Foo.prototype keyword in declaring all those public functions you might need.
So I came up with using some shorthand variable for convenience as follows.
(function(){
var Foo = function(){
alert('created Foo');
}
// shorthand for further creation of public functions
var pro = Foo.prototype;
//public function with shorthand
pro.bar = function(){
//some cool stuff here
}
return window.Foo = Foo;
}());
Question is: is there some reason to prevent me from saving these few characters regarding functionality or some unexpected error or is this safe to do?
This seems to work just fine for the cases I used it in?
As far as I know, prototypes is an object like any other when it comes to modifying it. Keeping a reference to it is absolutely ok
Edit:
It's OK to do so, but is sometimes confusing for that if you have code like this:
var pro='123';
(function () {
var Foo=function () {
alert('created Foo');
};
// shorthand for further creation of public functions
var pro=Foo.prototype;
var x=new Foo();
alert(pro);
})();
alert(pro);
or accidentally write it like this:
var pro='123';
(function () {
var Foo=function () {
alert('created Foo');
};
// use pro without var
pro=Foo.prototype;
var x=new Foo();
alert(pro);
})();
alert(pro);
The former will work properly, just it's confusing when reading the code, the reader need to be aware of that the var pro in the IIFE is not the same pro in the global scope.
The latter may be a terrible error that the pro is reassigned and lost its original value.
So I proposed the code as it's in my original answer because you cannot modify this inside the function.
I think you can do it in this way ..
var Foo=(function () {
function Foo() {
alert('created Foo');
}
// inside the anonymous function `this` is `Foo.prototype`
(function () {
this.bar=function () {
//some cool stuff here
};
}).call(Foo.prototype);
return Foo;
})();
var x=new Foo();
x.bar();

Consequences of Dynamically rewriting a function in 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.

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