Why is this variable not being initialized? - javascript

In the <head> of my page, I do this:
<script type="text/javascript" src="js/foo.js"></script>
<script type="text/javascript">
console.log(foo.bar);
</script>
Code of foo.js:
var foo = function()
{
this.bar = function()
{
console.log('here');
}
}
Later on in the html document:
Test
However if I click that link above, it says function not defined even though foo.js has been included. Also if I do console.log(foo) it only shows 'function()' and console.log(foo.bar) shows undefined. Why is this, why can't I access the function?

Because you haven't created an object. This is a correct way of running your code:
var foo = function()
{
this.bar = function()
{
console.log('here');
}
}
var instance = new foo();
instance.bar();
http://jsfiddle.net/zerkms/wDaEn/
Or, you can define it in another way:
var foo = {
bar: function() {
console.log('here');
}
};
foo.bar();​
http://jsfiddle.net/zerkms/wDaEn/1/

I'm not sure if you want it this way, but to get your console.log(foo.bar); to work you can do this:
var foo = {
bar: function() {
console.log('here');
}
};

Since you are using this and creating instance class member, you need to instantiate the class first:
var fooClass = new foo;
console.log(fooClass.bar());

For minimal code changes use the following:
<script type="text/javascript">
var foo = function()
{
this.bar = function()
{
console.log('here');
};
return this; // magic yes ?
};
foo().bar();
</script>

The content of foo.js just initializes foo to a function... What's in the implentation has no importance until foo() is called.
So foo.bar is undefined.

The above answers are not all correct, remember javascript has no concept of classes or instances of said classes. I would do some reading on Javascript scope and closures.
When you assign your object to the variable name bar, you are assigning it to the local scope. You are then attempting to access your local function from a global context. This is wrong.
I am willing to bet you are attempting something along the following:-
var foo = {
bar: function() {
}
}
Etc...

Related

JavaScript Function Hoisting in my Object

I have created an object and am attaching a bunch of functions to the object. I am concerned about how the ordering of the functions effects when I can call my functions. In my example below, I must define my functions first before I can use them. My problem with this is that I cannot call init() immediately until I have defined it. Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init(). So in the end, init() will have to be the very last function defined in my object. I believe this is related to Hoisting.
My question is if there is a way for me to call a function before defining it? Is there some sort of way to create a 'placeholder' function like in C?
https://jsfiddle.net/13hdbysh/1/
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
foo.init();
foo.init = function() {
console.log('init()');
};
})();
What you're asking deals with how objects store member data. This can be seen in a weird light because of prototypal inheritance. Javascript by default will parse naked functions before they execute.
Example:
(function() {
init();
function init()
{
console.log("Init");
}
)};
This gets muddied when storing behavior as a member to an object. Because prototypal inheritances dynamic functionality you need to declare your members before accessing them. This is Javascript's main difference from traditional OOP languages.
You mentioned, "is there a way to create a 'placeholder' function like in C." You can, but not in the same way. You can assign it to a naked function and assign that to your object. Look in my example, the hello function.
Alternatively you can store the behavior on the prototype of your object and override it when necessary.
Example:
function hello()
{
console.log("Hello my name is "+this.name);
}
(function() {
var something = function(name) {
this.name = name;
};
something.prototype.initTwo = function() {
console.log("My Name is: "+this.name);
};
var thingOne = new something("Thing One");
thingOne.init = "SomeThing";
var thingTwo = new something("Thing Two");
thingTwo.init = function() {
console.log(this.name);
};
thingTwo.initTwo = function() {
console.log("SomethingTwo is Named: "+this.name);
};
thingTwo.hello = hello;
console.log(thingOne.init);
thingTwo.init();
thingOne.initTwo();
thingTwo.initTwo();
thingTwo.hello();
}) ();
Demo: Fiddle
Documentation on objects in javascript.
Try using similar IIFE pattern
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
// foo.init();
foo.init = (function _foo() {
console.log('init()');
this.init = _foo;
return this.init
}).call(foo);
foo.init()
})();
jsfiddle https://jsfiddle.net/13hdbysh/2/
I am not sure why would you wanna call it before it is defined but here is how to do it:
foo = window.foo || { init: function() { } };
How about declaring it as a local variable first.
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
var initFunction = function() {
console.log('init()');
};
//this will no longer error
initFunction();
foo.init = initFunction;
})();
Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init().
You are operating under a misapprehension.
A function must be defined before you call it, not before you define another function which will call it later.
Just define all your functions and then start calling them.
(function() {
foo = window.foo || {};
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.init = function() {
console.log('init()');
};
foo.init();
foo.helloWorld();
})();
As far as hoisting is concerned, function declarations (you only have function expressions) are hoisted, but they create locally scoped variables, not object properties. You would have to assign them to object properties before you could call them as such, and that assignment wouldn't be hoisted.
It's throwing an error because you're calling the method init() before it's declared.
This way will works
foo.init = function() {
console.log('init()');
};
foo.init();
Since foo is an object, you can put those functions into an object so that will be assigned to foo once window.foo is null
(function() {
foo = window.foo || {
helloWorld: function() {
console.log('helloWorld()');
},
init: function() {
console.log('init()');
}
};
//this will not error
foo.helloWorld();
foo.init()
})();

Why can't I assign a function to a variable using prototype?

I keep on trying to assign a function to a variable and I keep getting a message saying foo is not a function. I am not sure why it is saying that. When I invoke the method by itself it works, but when I assign it to a variable it won't work.
Can anyone please help me figure this out? Thank you!!!
Below is my code:
function Test(){
function foo(){
return "foo";
}
this.bar = function () {
var foo = foo();
console.log(foo);
};
}
var test = new Test();
test.bar();
The culprit is this line var foo = foo();. The statement var foo is redeclaring the local foo variable. By the time you try to access it with foo() it has become an undefined variable.
Rename the variable or the function and everything works correctly.
Following code will work. As Now we are not trying to assign same function variable to variable.
The problem is because JavaScript is function scoped. It is failing because this.bar function will try to evaluate foo first and foo is name of variable in this function so interpreter will try to execute the foo but foo is variable in this scope it will not consider foo mentioned above. Hence it fails.
Where as foo1 will work because when interpreter hits the term foo1 it will look for current scope and all parent scopes and it will get it.
function Test(){
function foo1(){
return "foo";
}
this.bar = function () {
var foo = foo1();
console.log(foo);
};
}
var test = new Test();
test.bar();
Error is at this line
var foo = foo();
Your variable foo has the same name as the function, that hides the function outside.
Renaming it will resolve the error.
var foo1 = foo();
There error you're seeing is from this line:
var foo = foo();
When you use var there you are saying that foo is being defined for the current level of scope (this.bar) - meaning it won't bubble up to Test. You can either rename the variable to something else:
var result = foo();
console.log(result);
or just forgo that variable altogether like this:
console.log(foo());
totally your choice.
If you are learning how to create and work with JavaScript objects, you may want to rewrite your code like so:
// This function constructs the object when called with new
function Test(prop) {
// Some arbitrary property
if (typeof prop === "undefined") {
prop = null;
}
this.prop = prop;
}
// The two functions
Test.prototype.foo = function() {
return "foo";
}
Test.prototype.bar = function() {
var foo = this.foo();
console.log(foo);
}
// Create the object and call foo
var test = new Test('p');
test.bar();
All JavaScript objects inherit the properties and methods from their
prototype. Objects created using an object literal, or with new
Object(), inherit from a prototype called Object.prototype. Objects
created with new Date() inherit the Date.prototype. The
Object.prototype is on the top of the prototype chain.
From: http://www.w3schools.com/js/js_object_prototypes.asp

Access Parent method from child Javascript

How can I access baz() from inside the bar() function in the following code?
var obj = {
baz : function(){ alert("Hi!"); },
foo: {
bar: function(){
baz();
}
}
}
JavaScript doesn't have kind of a built-in parent reference because an object can be referenced by multiple 'parents' in what we call a many-to-one relationship.
As others have said, in this simplified case, simply calling obj.baz() will work.
In a more complicated case, you would have to manually build the object and track parenthood:
// Create the root object
var rootObject = {baz: function() {console.log('rootBaz');}}
// And the basic child
var childObject = {foo: function() {console.log('childFoo');}}
// Configure the parent
childObject.parent = rootObject;
// Add our call.
childObject.baz = function() {this.parent.baz()};
// Invoke and test
childObject.baz();
Which can be slightly simplified:
var rootObject = {
baz: function() {console.log('rootBaz');}
};
var childObject = {
foo: function() {console.log('childFoo');},
baz: function() {this.parent.baz()}
};
childObject.parent = rootObject;
childObject.baz();
Updated per Sujet's comment
In addition, if you need to make sure that baz has the correct value for this you can use either call or apply.
baz: function() {this.parent.baz.call(this.parent)}
If your code doesn't require this then I would recommend a straight function call per my original answer.
Just use the object reference:
var obj = {
baz : function(){ alert("Hi!"); },
foo: {
bar: function(){
obj.baz();
}
}
}
You need to reference via object.property notation.
In your example you would get baz via:
obj.baz()
Some great resources for this:
http://www.w3schools.com/js/js_objects.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects

Define an anonymous function as part of an object definition?

Suppose I have:
var myfunc = function() {
// do stuff
}
myfunc.foo = function() {
//do other stuff
};
Now myfunc has a property foo that is a function, great. Is there a way to create myfunc from the get-go in this state? That is, I want foo to be defined when myfunc is created. The syntax, I would imagine, is something like:
var myfunc = {
:function() {
// do stuff
},
foo: function() {
// do other stuff
}
}
Except that's wrong.
You can place an anonymous function inside an object, however the only plausible way of doing this is to call the anonymous function when the object is initialised, otherwise the function will never be able to be called - it's anonymous!
Here's a JSFiddle: http://jsfiddle.net/g105b/99K5F/
var myfunc = function() {
this.foo = function() {
console.log("myfunc.foo called!");
};
(function() {
console.log("Anonymous function called.");
})();
};
// Initialising "myfunc" will call the anonymous function.
var instance = new myfunc();
// Now the foo method can be called.
instance.foo();
A little confused as to what functionality you are looking to gain here...
If you want some code to execute when the myfunc is defined, you could use the module pattern:
var myfunc = (function() {
var self = {};
// any initialization code can go here
alert("myfunc init code");
self.somePublicMethod = function () {
}
return self;
}());
This can also be called an immediate function, a function that is defined and executed at the same time.
From within the closure, and code that is not defined as part of another function will be executed when the object is defined, so when you do something like this:
myfunc.somePublicMethod()
the alert would have already been fired.
(This answer written before the first half of the question was significantly revised)
Now myfunc has a property foo that is a function
No, it doesn't.
You called it with myfunc() so this is a reference to the global window object, thus you are creating window.foo.
Possibly what you are looking for is:
function myfunc () {
// do stuff when myfunc is called
}
myfunc.foo = function () {
// do stuff when myfunc.foo is called
};
or perhaps:
function myfunc () {
// do stuff when myfunc is instantiated
this.foo = function () {
// Add a foo property to this when myfunc is instantiated
// ... which is only worth while if you are doing pretty
// ... odd stuff with the variables that are passed in
}
}
var instance = new myfunc();
or maybe:
function myfunc () {
// do stuff when myfunc is instantiated
}
myfunc.prototype.foo = function () {
// Have a foo function on every instance of myfunc
}
var instance = new myfunc();
… but you've abstracted the problem you are trying to solve away in your question, so it is hard to tell what you are actually trying to achieve.
You can use jQuery:
var myFunc = jQuery.extend(
function() { ... },
{
bar: "wioll haven be",
foo: function() { alert(myFunc.bar); }
}
);
myFunc();
myFunc.foo();
This is mostly code acrobatics, this is probably the closest you'll get:
var myfunc;
(myfunc = function(){}).foo = function(){};
There is no practical difference in declaring methods later though, since javascript is single-threaded.

Java-script object - get variable name

To begin with, I'm not even sure, if it is the right way to do it.
Let's say, i have script (jquery included) like this:
foo = function() {
this.bar = function() {
alert('I\'m bar');
}
this.test = function() {
$('body').append('<a onclick="my_var.bar();">Click me</a>');
}
this.test();
}
var my_var = new foo();
Is there any way, i could make variable "my_var" dynamic inside function "foo".
So I could do something like
$('body').append('<a onclick="'+the_variable_which_im_assigned_to+'.bar();">Click me</a>');
Thank you
//Edit:
I'm sorry if i wasn't clear enough, because I'm not quite sure of what I'm trying to do myself.
My goal is to replace line
$('body').append('<a onclick="my_var.bar();">Click me</a>');
with
$('body').append('<a onclick="'+what_ever_should_go_here+'.bar();">Click me</a>');
So when i call
var my_var = new foo();
var your_var = new foo();
var our_var = new foo();
I would be able to call functions inside each object (after they append something into document body).
You should use anonymous handler functions instead of inline events, like this:
$('Click Me')
.click(function() { my_var.bar(); return false; })
.appendTo('body');
In addition to switching from the inline event handler, you'll need to use a closure to access the Foo instance within the handler.
function Foo() {
var self = this;
this.test = function() {
$('body').append(
$('<button>something</button>').click(function () {
self.bar(); return false;
}));
}
}
If that's the general plan you want/need to use to attach event handler, yeah, send in the name of the variable to the function that foo refers to:
foo = function(name_of_the_variable_which_im_assigned_to) { [...] };

Categories