Javascript function implementation - javascript

I have code like this :
(function() {
$(document).ready(function() {
//event handlers
$('.project-delete').on('click', function() {
deleteProject($(this));
});
$('.keyword-delete').on('click', function() {
deleteKeyword($(this));
});
this.deleteKeyword = function(model) {
}
}).call(this);
I am curious if this is a good approach since I was learning JS recently and as far as I understand this function will have global scope, doesn't it ? since .call(this) is passing window object to this closure then I think it is not the best option ? Is there something I am missing ? Does changing .call(this) to just () change anything ?
EDIT:So is it OK to just pass window object to that closure ? Wouldn't it better to pass just a empty object or jQuery object ?

Assuming this function is defined in the global scope, the deleteKeyword function will have also have global scope since this in the context of the parent function is basically window (which has been passed in as this from outside; in the global scope this === window).
If you change .call(this) to just (), this is still window inside the function. This is because when you call a function via a simple function-call, this is set to the global object, which is window.
If you want a different value for this, you will need to pass in something else via .call or .apply.
For more information about the behavior of this, take a look here.

"as far as I understand this function will have global scope, doesn't it?"
"Scope" is about what variables a function has access to (i.e., its own local variables, plus locals declared in any functions that it might be nested inside, plus global variables), and that has nothing to do with the value of this. Scope depends on where the function declaration is, but this depends on how the function is called.
"since .call(this) is passing window object to this closure"
We can't tell that just from the code shown. Presumably you mean that that block of code is not nested inside some other function, so then yes, this would be window. But if that code was ever pasted inside some other function then that this might have some other value depending on how that other function was called.
"Does changing .call(this) to just () change anything?"
If you use just () that will mean that inside the function this will be window. Whether that changes anything depends on whether the this in .call(this) was window in the first place - as I already mentioned above, if that block were nested inside some other function this could be something else. Having said that, for the code shown if this was anything other than window I think your code would break. Because you declare a function like this:
this.deleteKeyword = function(model) {...}
...and then inside the second click handler you call what I assume is meant to be the same function without using this:
deleteKeyword($(this));
The only way that will work is if this is window and the deleteKeyword() function is thus global. If this were any other object the function would be a property of that other object and thus not accessible directly as deleteKeyword(). But unless you specifically want deleteKeyword() to be accessible from other code not shown there is no reason to create it as a property of this at all. Just declare it with var:
var deleteKeyword = function(...
...and then it will be accessible only inside that function and the ones nested in it such as your click handler. And the .call() at the end of your function would be redundant since the function wouldn't ever actually use this.
"so isn't it a better option to apply jQuery object (or maybe just empty object) to it to increase performance? Wouldn't it increase performance if this would point to local scope? Since window object is very slow."
Well as I already said, "scope" and the value of this are unrelated concepts. I'm not sure why you are worrying about performance for that code. But if you were to apply jQuery or an empty object with .call(jQuery) or .call({}) the code would not work as explained above.

Related

eval calls function which calls eval which defines function

I know the title sounds convoluted, but to keep things dynamic there is a purpose for this rest assured ;)
Examples (note that these example codes are assumed to be within an outer eval)
//Ex1 this works
eval('function test (){}');
test();
//Ex2 this doesn't work (myfunction definition is written below)
myfunction();
test(); //I get an error
If I defined myfunction globally (outside of the outer eval) I get this error: object is not a function
If I defined myfunction within the outer eval I get this error: object is not a function
//myfunction definition
function myfunction () {eval('function test (){}');}
Question is: how do I expand the scope of a function definition to just outside of the function it was defined within? I know about making an eval global (see alternate myfunction below), but that seems like overkill, I just want to increase the scope to the outer eval is all. Is this possible?
Update:
The examples only define one function to keep is simple, but I wish expand it so that myfunction defines many functions, and what functions it defines is dynamic depending on other factors. Also I wish to retain the function names as well as the definitions. I may end up just putting the contents of myfunction into the outer eval if I can't find a solution other than making eval call globally, then I have to copy over the contents to everyplace that uses it.
//making eval global works, but I had hoped to just upscope to the calling eval
function myfunction(){var globaleval=eval;globaleval('function test(){}');}
Below has been edited since the initial question:
Maybe you could make a var in outer eval, have myfunction return the address of the function definition to that var. However, I wish to retain the function names as well as the definitions.
OK, so I am assuming you actually mean you want to control the scope in which eval uses...
Why not
eval.call(context, 'function test(){}');
example
eval.call(window, 'function test(){}');
eval() does execute within the local scope but that isn't your problem.
First, ditch eval()!
Second, think clearly on what you want without eval(). Even better please update the question when you have that.
Since I can't understand the actual question here are some guesses:
1. Reference to a particular object
If you want a reference to this of a particular object and the current context isn't sufficient Then use something like this question to "bind" (included in ecma 5) your new function to this.
You'll still have reference to the local closure of course.
2. Function that has a specific closure
If you want to call a function whose scope is "further out" or different than your "current scope" then define "that function" in the scope you want it to have (the closure) but then use a reference to "that function" that inner scope has
e.g.
var test='outer';
var outer = function (){ alert(test);}
(function(){
var test='inner';
var inner = function(){
alert(outer());
}
inner();
})()
You'll note that inner() returns "outer" in this example
in your second example function test() doesn't exists, because it's not defined yet )))

How does JavaScript assign context to this of event handlers?

After reading related questions #1 , #2
I still haven't found an answer to the following question:
Javascript can set context (i.e. set this) with: bind , call and apply.
But when I'm write an event handler:
document.getElementById('myInput').onclick = function ()
{
alert(this.value)
}
Who/What actually attaches this to the object itself ?
P.S. When using jQuery's :
$("#myInput").bind(function (){...})
there is an internal implementation of (bind, call or apply)
So when I am not using jQuery, who is doing it?
Why, the DOM/JavaScript of course, it's supposed to work that way by W3C.
Event handlers are invoked in the context of a particular object (the current event target) and are provided with the event object itself.
Source
How exactly that happens, we don't know. It's an implementation detail.
All we know is, that the semantics as defined by the W3C are achieved in some way, but which part of the browser does that and and how, that is left up to the browser developers, and they can implement it as they see fit.
To sum up all the discussions:
In general it is JavaScript that binds this to o inside a function call, when o.x() is called.
However, there are some alternative methods of calling functions (like f.apply() and f.call()) that change this behaviour.
onclick is a special case, and the method used to invoke it is unknown and depends on the DOM implementation.
The answers saying it is the DOM are wrong.
This is part of JavaScript itself, as a language. The DOM is ONLY what the name indicates "Document Object Model", which is just how HTML is represented for manipulation by using JavaScript. Objects related to the DOM follow the behavior specified by the standards, but this is implemented by using JS for it. It is the JS engine what does this, in communication with whatever layout engine is being used (Gecko, Trident, WebKit, Presto, etc.). So, if WebKit detects an event, it passes it to the JS engine as the DOM specification indicates so that it can manipulated by the JS programmer (which is why you're even asking about this, because you can work with it).
In other words, if you're writing something in JavaScript, the only engine that understands how to read and execute that is the JS engine. This engine (v8, SpiderMonkey/Jugger/Trace) will receive data from the layout engine and use it so that you can interact with it. Similarly, on the other hand, whenever you run code that affects the layout, the changes will be detected by the layout engine and it will change the layout so that the user perceives the changes: even if the JS code might have initiated this, it is the layout engine that takes care of the layout.
What "this" is when you assign a function to an object, is simply wherever the function belongs to. So, if you assign a function to instance of object a, then said function will refer to a whenever you use "this" inside of it.
If you wanted to think of it in implementation terms, think of it this way:
Whenever you are calling a method, you do so by first telling an instance that you want to call a method with N parameters. This instance calls the method but adds itself into the context, as "this".
In Python this is done more explicitly by making the first parameter of all instance methods the instance itself. Here it is the same, but the instance is passed implicitly instead of explicitly.
Remember, the instance owns the method. When you do "document.getElementById('something')" the call returns an object (which happens to be an HTMLElement object that is part of the DOM, but that's coincidental to how JS interacts with the DOM), and then you are assigning the function as the property click.
Then, whenever you call the method, the JavaScript engine passes the instance by default, just like it passes other variables (like arguments is also generated without you doing anything, also done by the JS engine which implements the ECMAScript standard).
I would recommend checking pages 63:
"The this keyword evaluates to the value of the ThisBinding of the current execution context."
but most importantly, page 68 "Function calls"
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
In your example, of an onclick handler it's perfectly straight forward: a DOM element is an object, you're defining the onclick property to be a function. That function effectively becomes a method of that DOMElement/object.When that object is clicked, the function is called as a method of that element, so this points to its owner, the element.
Put simply, the context in which the function executes is the same as the context in which is was created (again: in your example as a method of a DOM Element), unless a reference to a function object is assigned to another object, or when that function object is invoked in another context using call or apply & co.There's a little more to it than this, of course: as I hinted at above, functions are objects themselves and are said to be loosely coupled to their "owner". Well, actually they don't have an owner as such, each time a function is called, its context is determined:
var foo = someObject.someFunction;//reference to method
someObject.someFunction();//this === someObject, context is the object preceding the function
foo();//implies [window].foo(); ==> this is window, except for strict mode
As #wroniasty pointed out, my talking about ownership might be slightly confusing. The thing is, functions are objects, they're not owned by anything. When an object is assigned a method, all that object really owns is a reference to a given function object. When that function is called via that reference, this will point to the object that owned the calling reference. When we apply that to your elem.onclick = function(){}, we see the element only owns a reference to a function expression that was declared in some scope (global, namespace-object, doesn't matter). When the click event fired, that reference will be used to call the handler, thus assigning a reference to the element to this. To clarify:
document.getElementById('foo').onclick = (function()
{//This function returns the actual handler
var that = this;//closure var
console.log(this);//logs window object
//defined in global context
return function(e)//actual handler
{
console.log(this === that);//false
console.log(this);//elem
console.log(that);//window
};
})();//IIFE
So the handler was declared in the global context, and the handler can access its the context it was declared in using that, thanks to closures (but that's another story). The point is, the event references the handler using the onclick property of the element foo. That property is a reference to a function object, so the function object sets its context to whatever object made the call.
I do hope this clears up any confusion I caused with regard to ownership of functions, and perhaps how context in JS is determined.
http://dmitrysoshnikov.com/ecmascript/chapter-3-this/#this-value-in-the-function-code
Basically, it's done by JavaScript internals.
The context is the object calling the function, e.g.
elem.onclick(); // elem === this
However:
func = elem.onclick;
func() // global === this
This really has nothing to do with the DOM as has been mentioned, but how JavaScript is designed to work when you call a function within an object.
Take this as an example:
var myObject = {
id: 1,
onclick: null
}
myObject.onclick = function() {
console.log(this.id);
}
Calling myObject.onclick() will log 1 to the console, which means myObject is its context.
Since onclick is also a property of an object, this will be the parent object, in your case an HTMLElement.
For illustration purposes, although implementations may differ, think of the following function
function f() { alert(this.name); }
as
function f(this) { alert(this.name); }
Imagine this as a secret parameter that you can override with bind, apply and call but that normally gets set to the calling object by the browser.
Example
var a = {},
b = {};
a.name = "John";
b.name = "Tom";
// "this" param added secretly
function printName( ) {
console.log( this.name )
};
a.printName = printName
b.printName = printName;
When calling the printName function the browser sets that "secret" this parameter to the calling function. In the example below this is b and so "Tom" is printed to the console.
printName( ); // global context assumed so this === window
b.printName( ); // this === b and outputs "Tom"
printName.call( a ); //this === a and outputs "John"
Further info here.

How to run a local function from inside an jQ's AJAX request?

var main = {
doSomething: function(){
function firstOne(){}
function secondOne(){
$.ajax({
success: function(){
firstOne(); /* here I want the previous function */
}
});
}
}
}
How can I run the firstOne() function from the marked line? It's a noobish question perhaps, but I don't get the JS namespace (and I tried).
Is that kind of defining functions good from a JS good practices point of view?
What you do works. This passage of MDN explains why:
You can nest a function within a function. The nested (inner) function is private to its containing (outer) function. It also forms a closure.
...
Since a nested function is a closure, this means that a nested function can "inherit" the arguments and variables of its containing function. In other words, the inner function contains the scope of the outer function.
To summarize:
The inner function can be accessed only from statements in the outer function.
The inner function forms a closure: the inner function can use the arguments and variables of the outer function, while the outer function cannot use the arguments and variables of the inner function.
So this explains why you can call firstOne from within the Ajax callback.
Whether this is good design or not depends completely on what you are trying to achieve. If firstOne is something that you could reuse in several parts of your code, then it would certainly be a bad decision to define it as a nested function, where it can only be accessed in a local context. But if you had for example two Ajax calls within secondOne that both needed the same functionality in their callback, then it would be a good decision to wrap this in a local nested function. If you just need the behaviour once then it might be overkill (and extra typing) to declare it as a separate function.
Your code looks OK, and should run fine.
Unlike many other programming languages, Javascript has a scope lookup chain. If a function or variable is not found in the local scope, Javascript will look for it in the scope above that. If it's not found there either, it'll look for it further up in the chain, till it hits the head object (which in a browser would be the window object). If it's not found there, then it throws an error.
Since your firstOne() function is declared in the scope immediately above your AJAX object, Javascript should have no problem finding it for you. There's no need to manually reference the parent scope.

How can I get to the parent scope of my inline javascript callback function?

I have something similar to this
function testfunction(runthis)
{
runthis();
}
function main()
{
var z = 15;
testfunction(function(){ alert(z); });
}
However it doesn't think z is in the same scope as my inline function. Without adding additional parameters to testfunction or my inline function, is there any way for my inline function to belong to the same scope as main? I'm trying to make callback functions work.
Edit: the above I imagine is a crappy example because it seems to be working. However the instance here http://pastebin.com/A1pq8dJR does not work unless I add .call(this,parameters) and manually set the scope (although I'm not exactly sure what this is doing). I would have thought this used there would refer to the scope imageLoaded has, but it is referring to the scope of imageBoxCreate? Could anyone explain why it wont work without that and why doing this fixed it?
If you just invoke a global function in javascript, the this object will be the top level window global object. If you invoke a function using the dot operator on an object, then this will be that object when the function runs. When you use function.call, you are explicitly specifying which object should be this. I think you are likely just making some scope mistakes with how you use this and var, but your code is long enough and involved enough that I'm not going to spend the time to debug it for you. If you can isolate you issue with a smaller code sample, folks should be able to help more easily.

Is it good to write javascript functions inside functions and not use 'new' on the main function?

I now know this works:
function outerfunction(arg1, arg2, arg3) {
var others;
//Some code
innerFunction();
function innerFunction() {
//do some stuff
//I have access to the args and vars of the outerFunction also I can limit the scope of vars in the innerFunction..!
}
//Also
$.ajax({
success : secondInnerFunction;
});
function secondInnerFunction() {
// Has all the same benefits!
}
}
outerFunction();
So, I am not doing a 'new' on the outerFunction, but I am using it as an object! How correct is this, semantically?
There doesn't appear to be anything wrong with what you're doing. new is used to construct a new object from a function that is intended as a constructor function. Without new, no object is created; the function just executes and returns the result.
I assume you're confused about the closure, and how the functions and other variables belonging to the function scope are kept alive after the function exits. If that's the case, I suggest you take a look at the jibbering JavaScript FAQ.
You are not using the outer function as an object. You are using it to provide a closure. The border line is, admittedly, thin, but in this case, you are far away from objects, since you do not pass around any kind of handle to some more generic code invoking methods, all you do is limiting the scope of some variables to the code that needs to be able to see them.
JFTR, there is really no need to give the outer function a name. Just invoke it:
(function() { // just for variable scoping
var others;
...
})()
I do this sort of thing all the time. Yes - javascript blurs the boundary between objects and functions somewhat. Or perhaps, more correctly, a javascript function is just an object that is callable. You would only really use the 'new' prefix if you wanted to have multiple instances of the function. My only suggestion here is that its usually considered good practice to call a function after you've declared it (you are calling the innerFunction before it has been declared) - although that could be considered nit-picking.
This is a valid example.
Functions in JavaScript are first order objects. They can be passed as an argument, returned from a function or even set to a variable. Therefore they are called 'lambda'.
So when you are directly using this function (without new keyword) you are directly dealing with the function as an object. When u are using new keyword, you are dealing with an object instance of the function.

Categories

Resources