Suppose I have a function which returns an object :
getMyObject(){
//do stuff here
return object;
}
Is it bad practice to call a method (that doesn't return anything) on the function name itself:
getMyObject().method();
instead of assigning a variable to the return object and then calling the method on that variable :
var returnedObject = getMyObject();
returnedObject.method();
I am working with an html page that has many nested frames, and I have access to a function that returns one of these frames. The frame might be used several times within other functions in my script, and I was wondering if it would be ok for me to access the frame in the way asked above, or if it would be better to declare a global variable.
*EDIT: * Ahh I haven't gotten a chance to use jQuery. Good to know!
Yes, this is perfectly OK. jQuery for example uses this as well. It returns objects on which you can call methods immediatley. This is called chaining.
In your example, method chaining is the better practice IMHO. If a function returns an object, upon which you want to call a method, but you do not need to reference that object after calling that method, don't assign it to a variable.
Also, jQuery code does this all the time(1):
$('#foo').on('click',function(){});
/\ \\
|| \\
|| \\
function call returns jQ object <============|
\\ ||
\\call method "on" upon _||
(1)To clarify: I do not claim that all jQ methods return an object .attr() or .prop() don't. What I mean by "all the time" is actually that the scenario the OP describes is very common in jQ code (function call, invoke method on returned object):
var someString = $($('.foo').get(0)).attr('id');//tricky little bugger, this :)
var aBool = $('#foo').prop('checked');
Usually, no. Chaining method calls like that is usually simpler, more elegant, and easier to read. However, there are a few cases when it's better to use a variable.
If you use a method (or chain of methods) a lot of times, you can use a variable if it makes the code cleaner.
If the method takes a long time to process, it's better to cache the result. For example, if you have some method called calculateResults(), and it pulls data from a database, that takes some time. If the data doesn't change, you'll be incurring that cost for each call to the method. Better to store it in a variable and reuse it.
If the method has side effects, you should be careful about calling it more than once. Those side-effects will be inflicted each time you call it. Again, as an example, if you have a function like nextItem() that advances to the next item and returns it (a la Java iterators), then calling it more than intended will actually change the result. In this case, you have no choice but store the result, since calling it more than once will produce incorrect behavior.
Otherwise, chain away!
Related
Given that $thisObj is referenced multiple times in the function, would it be better practice to cache $(this) before passing it to myFunction($thisObj)?
function myFunction($thisObj) {
alert($thisObj.html());
alert($thisObj.html());
alert($thisObj.html());
}
Which way should it be called?
myFunction($(this));
OR
var $obj = $(this);
myFunction($obj);
Or does it not matter because the object is already "cached" once it's passed to the function? This seems like a very fundamental question, but I spent a lot of time searching this topic without a clear answer.
This doesn't make a difference inside myFunction() since the value is only calculated once when the function is called and then stored in the $thisObj parameter variable. The conde in the function just uses the contents of $thisObj, it does not evaluate $(this) repeatedly.
So I would prefer to call the function as myFunction($(this)) since it's more to the point without creating an unnecessary extra variable.
With the extra variable, somebody reading the code will wonder if that variable will be used again later on, making the code (slightly) harder to understand.
If I had the following object and prototyped functionality added on.
function Hello (input){
this.input = input
}
Hello.prototype.ajaxcall = function(id){
$.get("/ajax/method", {parameter:input}, function(data){
$("#"id).html(data);
});
}
Forgive the syntax if not completely correct but what it should be doing is taking in an element id, performing an ajax call and assigning the ajax call result to the innerHTML of the id. Will the fact that the ajaxcall function is shared across all instances of an object cause any problems with regards to what data will be assigned to which id if for example 20 object were all created together and had this function called immediately?
If this is the case, does it make sense to put asyncronous methods inside the object constructor instead?
What would happen if 20 objects would be created and the ajaxcall function would be called? Nothing much. The ajax calls would run asynchronously. When they have finished they are queued so that they run on the main thread when the current running operation on the main thread finished.
So the callback functions run all synchronous in a queue next time there's time for it. Nothing bad can happen here.
I don't understand your question about the constructor. What would that change? If you use your Hello objects they have an instance variable. This is is enclosed in the callback closure . Creating a new function doesn't change the value in another callback function.
If you use the same IDs the content could flash when the text changes and you don't know which callback would be ran last but that's the worst thing that could happen.
There should be no issue. You're calling the function 20 distinct times with 20 different ids.
Conceptually though. I'm not seeing why this is part of your object. The function does not use anything at all from the object itself.
This particular example would work. Your function makes no use of any instance variables, so it doesn't really make sense to declare it that way, but it makes even less sense to move it into the constructor. Still it will work because the id argument will not be shared between calls.
EDIT: So now that you've changed it so that it does use an instance variable you've got the syntax wrong, it needs to be
{parameter : this.input}
But aside from that it will still work. The asynchronous behaviour is not a problem for the code shown.
Excuse me first. because i don't know this is question is valid or not. i if any one clear my doubt then i am happy.
Basically : what is the different between calling a method like:
object.methodname();
$('#element').methodname();
calling both way is working, but what is the different between, in which criteria make first and second type of methods. is it available in the core javascript as well?
In case if i have a function is it possible to make 2 type of method call always?
Can any one give some good reference to understand correctly?
Thanks in advance.
The first syntax:
object.methodName();
Says to call a function, methodName(), that is defined as a property of object.
The second syntax:
$('#element').methodname();
Says to call a function called $() which (in order for this to work) must return an object and then call methodname() on that returned object.
You said that "calling both way is working," - so presumably you've got some code something like this:
var myObject = $('#element');
myObject.methodname();
This concept of storing the result of the $() function in a variable is commonly called "caching" the jQuery object, and is more efficient if you plan to call a lot of methods on that object because every time you call the jQuery $() function it creates another jQuery object.
"Is it available in the core javascript as well?" Yes, if you implement functions that return objects. That is, JS supports this (it would have to, since jQuery is just a JS library) but it doesn't happen automatically, you have to write appropriate function code. For example:
function getObject() {
return {
myMethod1 : function() { alert("myMethod1"); return this; },
myMethod2 : function() { alert("myMethod2"); return this; }
};
}
getObject().myMethod1().myMethod2();
In my opinion explaining this concept in more depth is beyond the scope of a Stack Overflow answer - you need to read some JavaScript tutorials. MDN's Working With Objects article is a good place to start once you have learned the JS fundamentals (it could be argued that working with objects is a JS fundamental, but obviously I mean even more fundamental stuff than that).
The difference is very subtle.
object.methodname();
This is when JavaScript has the object at hand.
$('#element').methodname();
If you are using jQuery, you are asking jQuery to select the object that has the id of #element. After that you invoke the method on the selected object.
I've always passed arguments to a function like so:
setValue('foo','#bar')
function setValue(val,ele){
$(ele).val(val);
};
Forgive the silly example. But recently I have been working on a project that has some functions that take a lot of arguments. So I started passing the arguments through as an object (not sure if that's the correct way to put that), like so:
setValue({
val:'foo',
ele:'#bar'
});
And then in the function:
function setValue(options){
var value = options.val;
var element = options.ele;
$(element).val(value);
};
My question is, is there a better way to do that? Is it common practice (or okay) to call these 'options'? And do you typically need to 'unpack' (for lack of a better term) the options and set local vars inside the function? I have been doing it this way in case one of them was not defined.
I'm really looking to not create bad habits and write a bunch of code that is ugly. Any help is appreciated and + by me. Thanks.
I do the exact same thing, except I don't declare a new variable for each option inside the function.
I think options is a good name for it although I shorten it to opts.
I always have a "default" object within the function that specify default values for each available option, even if its simply null. I use jQuery, so I can just use $.extend to merge the defaults and user-specified options like this: var opts = $.extend({}, defaults, opts);
I believe this is a great pattern. I've heard an options object like this referred to as a "builder object" in other languages (at least in the context of object creation). Here are some of the advantages:
Users of your function don't have to worry about what order the parameters are in. This is especially helpful in cases like yours where the method takes a lot of arguments. It's easy to get those mixed up, and JavaScript will not complain!
It's easy to make certain parameters optional (this comes in handy when writing a plugin or utility).
There are some pitfalls though. Specifically, the user of your function could not specify some of the options and your code would choke (note that this could also happen with a normal JS function: the user still doesn't have to supply the correct arguments). A good way for handling this is to provide default values for parameters that are not required:
var value = options.val || 0;
var element = options.ele || {};
$(element).val(value);
You could also return from the function immediately or throw an exception if the correct arguments aren't supplied.
A good resource for learning how to handle builder objects is to check out the source of things like jQueryUI.
I realize this question is a year old, but I think the cleanest way to pass an arbitrary number of arguments to a JavaScript function is using an array and the built in apply method:
fun.apply(object, [argsArray])
Where fun is the function, object is your scope/context in which you want the function to be executed and the argsArray is an array of the arguments (which can hold any number of arguments to be passed.
The current pitfall right now is that the arguments must be an array (literal or object) and not an array-like object such as {'arg' : 6, 'arg2' : "stuff"}. ECMAScript 5 will let you pass array-like objects, but it only seems to work in FireFox at the moment and not IE9 or Chrome.
If you look at the jQuery implementation, it uses an options class to handle most of the arbitrary-number-of-parameters functions, so I think you are in good company.
The other way is to test for arguments.length, but that only works if your arguments are always in the same order of optionality.
It's worth remembering that all functions have a bonus parameter called arguments that is an object very much like a JS array (it has length but none of the array functions) that contains all the parameters passed in.
Useful if you want to pass in a range of parameters (e.g.
function Sum() {
var i, sum = 0;
for (i=0; i < arguments.length; i++){
sum+=arguments[i];
}
return sum;
};
If this isn't the case and you just have a lot of parameters, use the params object as you've described.
Nothing wrong with that practice.
"Options" seems like as good a name as any.
You don't need to "unpack" them, but if you'll be accessing the same item several times, it will be a little more efficient to reference them in local variables because local variable access is generally quicker than property lookups.
Could someone write down a very simple basic example in javascript to conceptualize (and hopefully make me understand) how the jQuery plugin design pattern is done and how it works?
I'm not interested in how creating plugin for jQuery (so no jQuery code here at all).
I'm interested in a simple explanation (maybe with a bit of Javascript code) to explain how it is done the plugin concept.
Plz do not reply me to go and read jQuery code, I tried, but I it's too complex, otherwise I would have not post a question here.
Thanks!
jQuery has a library of functions stored in an internal object named fn. These are the ones that you can call on every jQuery object.
When you do $("div.someClass") you get a jQuery object containing all <div> elements of that class. Now you can do $("div.someClass").each( someFunction ) to apply someFunction to each of them. This means, that each() is one of the functions stored in fn (a built-in one in this case).
If you extend (add to) the internal fn object, then you automatically make available your custom function to the same syntax. Lets assume you have a function that logs all elements to the console, called log(). You could append this function to $.fn, and then use it as $("div.someClass").log().
Every function appended to the fn object will be called in such a way that inside the function body, the this keyword will point to the jQuery object you've used.
Common practice is to return this at the end of the custom function, so that method chaining does not break: $("div.someClass").log().each( someFunction ).
There are several ways to append functions to the $.fn object, some safer than others. A pretty safe one is to do:
jQuery.fn.extend({
foo: function() {
this.each( function() { console.log(this.tagName); } );
return this;
}
})
Tomalak already posted almost everything You need to know.
There is one last thing that helps jQuery do the trick with the this keyword.
it's amethod called apply()
var somefunction=function(){
alert(this.text);
}
var anObject={text:"hello"};
somefunction.apply(anObject);
//alert "hello" will happen
It really helps in creating abstractions so that framework/plugin users would just use this as intuition tells them, whatever there is inside Your code
It works, as many other js frameworks, using javascript prototype orientation.
For instance you can declare a simple function
var alertHelloWorld = function() {
alert('hello world');
}
And then tie it to an existing object (including DOM nodes)
document.doMyAlert = alertHelloWorld;
If you do this
document.doMyAlert();
The alertHelloWorld function will be executed
You can read more about javascript object prototyping here