Reputation: 1570
I am using the following code but it is constantly giving me errors :
TypeError: container("accounts").atPosition("#left-top") is undefined
the code is :
function container(name, position) {
return {
pos: null,
atPosition: function(position) {
$(position).html(this.newContainer());
//$(position+" .main").html("yes");
this.pos = position;
},
populateData: function(rdata) {
$("#left-top .main").html(rdata);
},
newContainer: function() {
//alert(this.pos);
return '<h3>' + name.toTitleCase() + '</h3>\
<div class="main">\
</div>';
}
};
}
container('accounts').atPosition('#left-top').populateData("yahoo!!!!");
Why am I receiving this error and how can I fix it?
Upvotes: 1
Views: 879
Reputation: 10484
function chaining is not a special javascript syntax, if you want, you can implement it in Java, Python or anything that supports OOP.
a.functionX().functionY()
works because functionX()
returns again an object which has a method called functionY()
in your case, functionX()
should return the same object it is invoked on, therefore return this;
will fix your problem
But this is not the end of the story!!!
@Rich S mentioned in his answer:
In order to make chaining work, you need to "return this;" at the end of any functions you want to chain.
which is not necessary true, chaining will work as long as you return an object(or any object), here is an example:
var str ="abc";
var strFromChain = str.replace('a','x').toUpperCase();
// use function chainning
document.write(strFromChain+'\n');
// result should be XBC
var str1 = "abc";
str1.replace('a','x');
var str1NotFromChain = str1.toUpperCase();
// if replace() returned this, str1NotFromChain should also be XBC
document.write(str1NotFromChain)
// but is it???????
Obviously replace()
method of str
did not return this
instead it returned a new string with a different value, and this is easy to understand since strings are immutables, no matter what methods you call on str
, its value will always be "abc"
.
I am just making a point here, it's not necessary for chaining method to return this
, it can return a new object if it wants to. Even though online tutorials teach you to use this
when implementing chaining functions (ie javascript.issexy) you should always pay attention to what is being returned when using a third party library(ie route chainning in expressjs)
Upvotes: 1
Reputation: 23208
You supposed to return this
from functions for chaining. By default function return undefined (if you dont use new operator
) . by returning this from function which don't have any thing to return will help in chaining.
function container(name, position) {
return {
pos: null,
atPosition: function(position) {
$(position).html(this.newContainer());
//$(position+" .main").html("yes");
this.pos = position;
return this;
},
populateData: function(rdata) {
$("#left-top .main").html(rdata);
return this;
},
newContainer: function() {
//alert(this.pos);
return '<h3>' + name.toTitleCase() + '</h3>\
<div class="main">\
</div>';
}
};
}
Upvotes: 7
Reputation: 418
Chaining doesn't happen automatically.
In order to make chaining work, you need to "return this;" at the end of any functions you want to chain.
In reality, all you're doing is calling the function on whatever you return. If you do "return this;" then you end up with a nice chaining syntax that affects the same object.
The jQuery developer guide is a good place to get quality JavaScript tips from, given your question, I'd recommend looking at http://docs.jquery.com/Plugins/Authoring#Maintaining_Chainability
Upvotes: 0
Reputation: 943510
The function you assign to atPosition
doesn't have a return
statement.
So when you call atPosition('#left-top')
, you get the default return value of undefined
You need to return the object you wish to call populateData
on (which should be this
)
Upvotes: 2