Javascript this vs using same var name within itself - javascript

I am new to Javascript, can someone please help me understand if there is a fundamental difference between these 2 ways
First where I use this to call a function defined inside the var itself
var TxMmm={
name: {},
timeout: 2000,
testFunc1: function(){
console.log("testFunc1");
testFunc2();
this.testFunc3();
},
testFunc3: function(){
console.log("Test func3");
}
}
function testFunc2(){
console.log("This is func2 is outside var");
}
v/s Below where I use the var TxMmm to call function defined inside itself.
var TxMmm={
name: {},
timeout: 2000,
testFunc1: function(){
console.log("testFunc1");
testFunc2();
TxMmm.testFunc3();
},
testFunc3: function(){
console.log("Test func3");
}
}
function testFunc2(){
console.log("This is func2 is outside var");
}

In that specific code there isn't that much difference, because the object is a singleton. Some differences:
In your first code block using this, this could refer to something other than the TxMmm object in (say) testFunc1, depending on how testFunc1 is called. For instance, this would fail:
const fn = TxMmm.testFunc1;
fn();
But in your second code block, TxMmm will refer to the object (unless the next point comes into play), so that would work. More here and here.
If someone does:
const x = TxMmm;
TxMmm = somethingElse;
x.testFunc1();
...your first code block using this will keep working, because this is set by how testFunc1 is called. But your second code block using TxMmm would fail, because TxMmm doesn't point to the object anymore.
It almost never matters (seriously, very nearly never), but in your second code block, when you use TxMmm, the JavaScript engine has to look up that identifer to find it in the enclosing scope. Your code using this is able to resolve it immediately (since those aren't arrow functions), which in very rare situations can be faster in a noticeable way.
For non-singleton objects, this can be very important, since it tells the code which object's properties to use.

Related

Javascript: Dynamically add functions to object

I have a GeneralWrapper object that calls the statically-defined functions in the Library1 and Library2 objects.
The aim is that by calling GeneralWrapper.someFunc(), this will also call Library1.someFunc() and Library2.someFunc() without me having to explicitly create a function in GeneralWrapper called someFunc.
I attempt to implement this in the __preamble method below:
var GeneralWrapper = {
__modespopulated: false,
__validmodes: { // All 3 of these
spoonFunc: 1, // functions exist
knifeFunc: 1, // in Library1 and
forkFunc: 1 // Library2
},
__switchMode: function(funcname){
if (funcname in GeneralWrapper.__validmodes){
console.log("calling function", funcname)
GeneralWrapper.__preamble()
Library1[ funcname ](); // Call mode in Library1
Library2[ funcname ](); // Call mode in Library2
}
},
/* Attach valid modes to General Wrapper at runtime */
__preamble: function(){
if (!GeneralWrapper.__modespopulated)
{
for (var mode in GeneralWrapper.__validmodes)
{
GeneralWrapper[mode] = function(){
GeneralWrapper.__switchMode(mode)
};
}
GeneralWrapper.__modespopulated = true
}
GeneralWrapper.__otherprestuff();
},
__otherprestuff: function(){
// Stuff
},
funcThatAlwaysGetsCalled: function(){
GeneralWrapper.__switchMode("forkFunc");
}
}
var Library1 = {
forkFunc(){console.log("Lib1","fork")},
spoonFunc(){console.log("Lib1","spoon")},
knifeFunc(){console.log("Lib1","knife")}
}
var Library2 = {
forkFunc(){console.log("Lib2","FORK")},
spoonFunc(){console.log("Lib2","SPOON")},
knifeFunc(){console.log("Lib2","KNIFE")}
}
// Okay, let's initialise the object
GeneralWrapper.funcThatAlwaysGetsCalled();
For some reason calls to GeneralWrapper.spoonFunc() and GeneralWrapper.knifeFunc() always defer to the Fork output.
I imagine the problem stems from the anonymous function assignment on the GeneralWrapper[mode] = blah line where JS treats it as the same function each time, but I don't know how to get around this.
Please advise.
Solution:
Change this line:
for (var mode in GeneralWrapper.__validmodes)
into this:
for (let mode in GeneralWrapper.__validmodes)
Explanation:
what happens in your code (when binding functions in __preamble's loop) is that you create an anonymous function, which is totally fine. The problem is, your anon function has received the mode as a reference to local variable, so it's value is not automatically cloned but rather accessed at runtime. The main problem is that you've used var keyword, which means "hoisted variable" (it gets declared at the top of the function it was defined inside, even if it's somewhere in the middle of your function's code). In this scenario, you need a "block-scoped" variable, which will be bound to each loop iteration separately.
You can read more about variables hostings on MDN:
var at MDN
let at MDN
One thing you have to know - let was introduced in ES2015, so if you worry about backward compatibility with older browsers, you either have to use Function.prototype.bind or IIFE
One potential problem here is that you're creating functions inside a loop which can lead to some performance problems or unexpected behavior.
I'd replace:
for (var mode in GeneralWrapper.__validmodes)
{
GeneralWrapper[mode] = function(){
GeneralWrapper.__switchMode(mode)
};
}
with:
for (var mode in GeneralWrapper.__validmodes)
{
GeneralWrapper[mode] = GeneralWrapper.__switchMode.bind(this, mode);
}
Which should solve the problem at hand.

How do I make a nonexistent (non-member, non-global) method invocable without using eval?

Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.

Access a javascript variable from a function inside a variable

Hello i have the following issue i am not quite sure how to search for it:
function(){
var sites;
var controller = {
list: function(){
sites = "some value";
}
}
}
So the question is how to access the sites variable from the top defined as
var sites
EDIT:
Here is a more complete part. i am Using marionette.js. i don't want to define the variable attached to the Module (code below) variable but keep it private to the Module, hope that makes sense. Here is the code that works:
Admin.module("Site", function(Module, App, Backbone, Marionette, $, _ ) {
Module.sites = null;
Module.Controller = {
list: function (id) {
Module.sites = App.request("site:entities");
}
};
});
and i would like instead of
Module.sites=null;
to do
var sites;
That sort of thing does make a difference right? Because in the first case i would be defining an accessible variable from outside where as the second case it would be a private one. i am a bit new to javascript so please try to make it simple.
if you are looking for global access, just declare the variable outside the function first, make your changes to the variable inside the function, then you can get the value whenever you need it.
I have found some info on this: sadly what i am trying to do doesn't seem possible.
Can I access a private variable of a Marionette module in a second definition of that module?
So i guess i have to do _variable to make developers know its private.
Disclaimer: I have no experience using Marionette, however, what you're describing sounds very doable.
One of the most powerful (in my opinion) features of JavaScript is closures. What this means is that any function declared from within another function has access to the variables declared in the outer function.
For example:
var func;
function foo() {
var answer = 42;
func = function () {
// I have access to variable answer from in here.
return answer++;
};
}
// By calling foo(), I will assign the function func that has access "answer"
foo();
// Now I can call the func() function and it has access to the "answer"
// variable even though it was in a scope that doesn't exist anymore.
// Outputs:
// 42
// 43
console.log(func());
console.log(func());
What this means is that if you declare var sites from within your module definition function as you described, you should have access to it from within any of your inner anonymous functions. The only exception is if Marionette is re-writing your functions (by using the Function function and toString()), which seems unlikely but possible.
Your original example should would as described, my suspicion is that there is something else going wrong with the code that is unrelated to your scope.

How does browser read the JavaScripts, which should come first (set on the top):event? function? or sub function

A simple question.
I have a web project includes multi JavaScripts.
JS:
// (1) Event
$('.input').keyup(function()
{
keyUpFunction();
});
// (2) Function
function keyUpFunction(){ ... }
(1),(2) which should come first in one javascript file? If the browser read the function first, does it store the function in memory and invoke it when scan the event.
In some case, the same function is defined in multi javascript . e.g.
prm.add_endRequest(function() {
fn1();
fn2();
});
$(document).ready(.......)
Should I duplicate the function name and define each component in each js file.
or keep the function declare in one file and invoke sub-function composite the function?
Functions defined in the following manner:
function fooBar(){}
Are 'hoisted' to the top of the current scope. This means they will always be available, in the current scope, even if they are defined at the end of the file.
This does not hold true if you defined you functions like this:
var fooBar = function(){};
These functions are not hoisted, and must be defined before they can be used.
It should be noted that in your specific example, keyUpFunction will only be called once a keyup event has fired. This also means that all javascript on your page will already be evaluated, so the keyUpFunction will be defined (parsed) already regardless.
EDIT: To be more explicit, this first example is okay:
doSomething('hello world');
function doSomething(str){
console.log(str);
}
However, this will cause you problems:
doSomething('hello world');
var doSomething = function(str){
console.log(str);
}
#Matt's answer covers the function hoisting stuff nicely.
To avoid function name clashes within multiple files, wrap your content in an immediately invoked function expression, e.g.:
(function() {
// put your variables functions here
...
// register event handlers
})();
Any variables or functions declared therein will be constrained to that scope.

jQuery Function Implementation and Function Call?

What is the difference of calling function like:
testCall: function() and function testCall() in jQuery ?
Update:
Questions: Does usage of one over the another have some performance issues related to it OR it really does not matter which one you are using ?
Update 2
Also other thing that I noticed that whenn I am defining function using testCall: function() and I call it using this.testCall() it works fine and am able to call it in any other function.
But when I am using function testCall() and I try to call it using testCall() in another function than I am getting errors and am not able to call it. Is this possible or there could be some other reason for the errors ?
In this example:
testCall: function()
testCall is now a function available on the object you're in, like this: object.testCall() It can access other functions, properties, etc inside this object if it needs to.
In this version:
function testCall()
testCall is just a globally available method, not scoped to the object or plugin, whatever you're dealing with, you can call it from anywhere, like this: testCall()
This is really a question about Javascript syntax (and semantics), not jQuery.
Both of those constructions define functions. This:
var x = {
// ...
name: function() { /* ... */ },
// ...
};
defines a function (an anonymous function) and assigns it as the value of the property called "name" in the object being assigned to the variable "x".
This:
function name() {
/* ... */
}
defines a function with the name "name". The effect is similar to:
var name = function() { /* ... */ };
but definitely different. However, for most purposes it's safe to think about them as being almost the same. The effect is that "name" is bound to the function in the lexically-enclosing scope. If you do that definition outside of any other function, then "name" becomes a property of the "window" object, and the function is therefore globally available. If that declaration is inside another function, then "name" is only available inside that function.
Usually you see the first form when you're doing something like setting up callbacks for some jQuery facility, like a UI plugin or $.ajax. You're giving jQuery a function that it should call upon something happening — an AJAX call finishing, or a use action like a mouse click, or completion of some sort of animation.
edit oh, and finally here's another note. If you define a function the second way, well then you can refer to that function by name and use it in an object definition (like the first example):
function globalFunction() {
function localFunction() { /* ... */ };
jQuery.something({
x: 100, y: 100,
callback: localFunction,
// ...
});
}
Many more such things are possible - functions are values in Javascript and can be tossed around as easily as numbers and strings.
The first (testCall: function()) is object literal notation for defining a function and assigning it to a property on an object (not shown). The function itself is anonymous; the property it is bound to has a name, but the function does not.
The second (function testCall()) is a named function.
Named functions have several advantages over anonymous ones, and so though you see the first format quite a lot, I would recommend using it sparingly if at all. Named functions can be reported usefully by your tools (debuggers and the like), whereas anonymous functions just show up as ? or (anonymous). More here.
For that reason, rather than this:
function doSomeNiftyAjaxyThing(foo) {
$.ajax({
url: "blah",
success: function() {
// Do something involving the successful result and `foo`
foo.bar();
}
});
}
I would typically do this instead:
function doSomeNiftyAjaxyThing(foo) {
$.ajax({
url: "blah",
success: niftySuccess
});
function niftySuccess() {
// Do something involving the successful result and `foo`
foo.bar();
}
}
Not only does this keep my code a bit cleaner (er, to my mind), but it means that if something goes wrong inside niftySuccess, I've given the function a name my tools can report to me. Note that other than the fact that the function has a name, they're identical – both functions are closures over the foo argument and anything else inside doSomeNiftyAjaxyThing.
You might be tempted to give the function a name inline, like so:
function doSomeNiftyAjaxyThing(foo) {
$.ajax({
url: "blah",
success: function niftySuccess() { // <== change here, PROBLEMATIC
// Do something involving the successful result and `foo`
foo.bar();
}
});
}
There you're declaring a function with a name as an expression, and assigning the result of the expression to a property. Arguably you should be able to do that, but there are a series of implementation...anomalies in the various Javascript engines out there that prevent your being able to do that. (More in the article linked above, and in this article.)

Categories

Resources