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
Related
I am having trouble calling the object method,it always throw a error this.b
is not a function
var a={
b:()=>"3333",
c:()=>this.b();
}
console.log(a.c());
Your code does not work because the arrow function binds the function to the scope in which it is defined. In this case, you are in the global scope when you create the function "c" using the arrow function. Often this can be fixed with a bind call. However, in this case, I would just convert to a classical function. This is a good lesson in why you should not be lazy and use the arrow function to save a few characters. The arrow function IS NOT the same as a normal function and can lead to hard to debug bugs.
var a={
b:()=>"3333",
c:function () { return this.b() }
}
console.log(a.c())
Simplest way to make your code working is to use a instead of this
var a = {
b: () => "3333",
c: () => a.b()
};
console.log(a.c());
Basically, the reference of c, will call the value based on lexical scope, the same of 'window.c()'.
To fix your implementation, do:
var a={
b:()=>{ return "333"; },
c:function(){ return this.b(); }
}
console.log(a.c()); // Here we have a "333"
Why this happens?
The function expressions work about dynamic scope, different of Arrow Functions. To access Object Properties and reference to same this, use { yourProperty: function() { return "Hello, World"; } }
Here's a sample of a simple Javascript class with a public and private method (fiddle: http://jsfiddle.net/gY4mh/).
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction();
}
}
ex = new Example;
ex.publicFunction();
Calling the private function from the public one results in "this" being the window object. How should I ensure my private methods are called with the class context and not window? Would this be undesirable?
Using closure. Basically any variable declared in function, remains available to functions inside that function :
var Example = (function() {
function Example() {
var self = this; // variable in function Example
function privateFunction() {
// The variable self is available to this function even after Example returns.
console.log(self);
}
self.publicFunction = function() {
privateFunction();
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
Another approach is to use "apply" to explicitly set what the methods "this" should be bound to.
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.apply(foo, null);
// => foo
Yet another approach is to use "call":
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.call(foo, null);
// => foo
both "apply" and "call" take the object that you want to bind "this" to as the first argument and an array of arguments to pass in to the method you are calling as the second arg.
It is worth understanding how the value of this in javascript is determined in addition to just having someone tell you a code fix. In javascript, this is determined the following ways:
If you call a function via an object property as in object.method(), then this will be set to the object inside the method.
If you call a function directly without any object reference such as function(), then this will be set to either the global object (window in a browser) or in strict mode, it will be set to undefined.
If you create a new object with the new operator, then the constructor function for that object will be called with the value of this set to the newly created object instance. You can think of this as the same as item 1 above, the object is created and then the constructor method on it is called.
If you call a function with .call() or .apply() as in function.call(xxx), then you can determine exactly what this is set to by what argument you pass to .call() or .apply(). You can read more about .call() here and .apply() here on MDN.
If you use function.bind(xxx) this creates a small stub function that makes sure your function is called with the desired value of this. Internally, this likely just uses .apply(), but it's a shortcut for when you want a single callback function that will have the right value of this when it's called (when you aren't the direct caller of the function).
In a callback function, the caller of the callback function is responsible for determining the desired value of this. For example, in an event handler callback function, the browser generally sets this to be the DOM object that is handling the event.
There's a nice summary of these various methods here on MDN.
So, in your case, you are making a normal function call when you call privateFunction(). So, as expected the value of this is set as in option 2 above.
If you want to explictly set it to the current value of this in your method, then you can do so like this:
var Example = (function() {
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction.call(this);
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
Other methods such as using a closure and defined var that = this are best used for the case of callback functions when you are not the caller of the function and thus can't use 1-4. There is no reason to do it that way in your particular case. I would say that using .call() is a better practice. Then, your function can actually use this and can behave like a private method which appears to be the behavior you seek.
I guess most used way to get this done is by simply caching (storing) the value of this in a local context variable
function Example() {
var that = this;
// ...
function privateFunction() {
console.log(that);
}
this.publicFunction = function() {
privateFunction();
}
}
a more convenient way is to invoke Function.prototype.bind to bind a context to a function (forever). However, the only restriction here is that this requires a ES5-ready browser and bound functions are slightly slower.
var privateFunction = function() {
console.log(this);
}.bind(this);
I would say the proper way is to use prototyping since it was after all how Javascript was designed. So:
var Example = function(){
this.prop = 'whatever';
}
Example.prototype.fn_1 = function(){
console.log(this.prop);
return this
}
Example.prototype.fn_2 = function(){
this.prop = 'not whatever';
return this
}
var e = new Example();
e.fn_1() //whatever
e.fn_2().fn_1() //not whatever
Here's a fiddle http://jsfiddle.net/BFm2V/
If you're not using EcmaScript5, I'd recommend using Underscore's (or LoDash's) bind function.
In addition to the other answers given here, if you don't have an ES5-ready browser, you can create your own "permanently-bound function" quite simply with code like so:
function boundFn(thisobj, fn) {
return function() {
fn.apply(thisobj, arguments);
};
}
Then use it like this:
var Example = (function() {
function Example() {
var privateFunction = boundFn(this, function() {
// "this" inside here is the same "this" that was passed to boundFn.
console.log(this);
});
this.publicFunction = function() {
privateFunction();
}
}
return Example;
}()); // I prefer this order of parentheses
VoilĂ -- this is magically the outer context's this instead of the inner one!
You can even get ES5-like functionality if it's missing in your browser like so (this does nothing if you already have it):
if (!Function.prototype.bind) {
Function.prototype.bind = function (thisobj) {
var that = this;
return function() {
that.apply(thisobj, arguments);
};
}:
}
Then use var yourFunction = function() {}.bind(thisobj); exactly the same way.
ES5-like code that is fully compliant (as possible), checking parameter types and so on, can be found at mozilla Function.prototype.bind. There are some differences that could trip you up if you're doing a few different advanced things with functions, so read up on it at the link if you want to go that route.
I would say assigning self to this is a common technique:
function Example() {
var self = this;
function privateFunction() {
console.log(self);
}
self.publicFunction = function() {
privateFunction();
};
}
Using apply (as others have suggested) also works, though it's a bit more complex in my opinion.
It might be beyond the scope of this question, but I would also recommend considering a different approach to JavaScript where you actually don't use the this keyword at all. A former colleague of mine at ThoughtWorks, Pete Hodgson, wrote a really helpful article, Class-less JavaScript, explaining one way to do this.
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.
I got a piece of code for javascript which I just do not understand:
function dmy(d) {
function pad2(n) {
return (n < 10) ? '0' + n : n;
}
return pad2(d.getUTCDate()) + '/' +
pad2(d.getUTCMonth() + 1) + '/' +
d.getUTCFullYear();
}
function outerFunc(base) {
var punc = "!";
//inner function
function returnString(ext) {
return base + ext + punc;
}
return returnString;
}
How can a function be defined within another function? Can we call pad2() from outside of my() function?
Please put some light on it. Thanks
Functions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.
The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:
function foo(doBar)
{
function bar()
{
console.log( 'bar' );
}
function baz()
{
console.log( 'baz' );
}
window.baz = baz;
if ( doBar ) bar();
}
In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.
as a different example:
function Fizz(qux)
{
this.buzz = function(){
console.log( qux );
};
}
The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:
const obj = new Fizz();
obj.buzz();
or more concisely (if you don't need to keep the object after calling buzz):
new Fizz().buzz();
It is called closure.
Basically, the function defined within other function is accessible only within this function. But may be passed as a result and then this result may be called.
It is a very powerful feature. You can see more explanation here:
javascript_closures_for_dummies.html mirror on Archive.org
function x() {}
is equivalent (or very similar) to
var x = function() {}
unless I'm mistaken.
So there is nothing funny going on.
Function-instantiation is allowed inside and outside of functions. Inside those functions, just like variables, the nested functions are local and therefore cannot be obtained from the outside scope.
function foo() {
function bar() {
return 1;
}
return bar();
}
foo manipulates bar within itself. bar cannot be touched from the outer scope unless it is defined in the outer scope.
So this will not work:
function foo() {
function bar() {
return 1;
}
}
bar(); // throws error: bar is not defined
When you declare a function within a function, the inner functions are only available in the scope in which they are declared, or in your case, the pad2 can only be called in the dmy scope.
All the variables existing in dmy are visible in pad2, but it doesn't happen the other way around :D
It's perfectly normal in JavaScript (and many languages) to have functions inside functions.
Take the time to learn the language, don't use it on the basis that it's similar to what you already know. I'd suggest watching Douglas Crockford's series of YUI presentations on JavaScript, with special focus on Act III: Function the Ultimate (link to video download, slides, and transcript)
function foo() {
function bar() {
return 1;
}
}
bar();
Will throw an error.
Since bar is defined inside foo, bar will only be accessible inside foo.
To use bar you need to run it inside foo.
function foo() {
function bar() {
return 1;
}
bar();
}
Nested functions can be the basis for writing a modular group of related functions, kind of halfway to full object-oriented programming (static classes only).
Here is an example of such a group of functions, in this case to convert a value to a JSON string or a JSON string to a value.
Notice how the inner functions are grouped into an Object inside an outer function, and how the Object is then stored into a group name. This is the only name directly visible from outside the group. To reach any contained function from outside, you just write the group name, a period, then the function name. To reach a contained function from inside, you can use the same notation, or 'this', a period, then the function name.
//--------------------------------------------------------------------//
// Module J:
// Convert from and to JSON strings
//--------------------------------------------------------------------//
const J=NewJ();
function NewJ()
{
const mod=
{
From:(str)=>
{
return JSON.parse(str);
}, // From
To:(val)=>
{
return JSON.stringify(val,null,3);
} // To
}; // mod
return mod;
} // NewJ
//--------------------------------------------------------------------//
// End Module J
//--------------------------------------------------------------------//
Here's a test:
console.log(J.To({A:'a'}));
Console output:
{
"A": "a"
}
What does the following javascript code mean? I guess it's defining a function within a function to make it look like OOP? Why the function can return multiple functions? what is the bracket at the end?
var grid_ui = function () {
function setup_data_source() {}
return {
init: function () {},
set_ds: function(rpt_headers, rpt_rows) {}
} // return
}();
The { } notation is called an object literal. It is same as:
a = new Object();
a.init = function() { };
a.set_ds = function(...) { };
return a;
and return { } returns an object.
The function () { ... }(); is a self-invoking function: it creates an anonymous function them immidiately invokes it.
In your code, the self-invoking function returns an object of functions, which is a namespace pattern. The value of grid_ui now contains { init: ..., set_ds: ... }, which is mentioned in return.
These concepts are very difficult to explain in one SO answer, so I will provide you some links:
http://www.hunlock.com/blogs/Functional_Javascript/
http://www.dustindiaz.com/namespace-your-javascript/
it is defining an function then calling it and taking the return value and assigning it to grid_ui.
the value of grid_ui is now the object (also called a dictionary) containing the keys init and set_ds.
In javascript, you can define functions within functions and assign functions to variables.
Now you can make calls like grid_ui.init() and grid_ui.set_ds("test", 1).
It is OOP. Functions are objects in JavaScript.
This code means that there is a variable, grid_ui, which evaluates to an object that has two "public" functions, init and set_ds. init and set_ds also have a context which includes a "private" function, setup_data_source.
There are no brackets.