Is there a way to do function overloading in Javascript? - javascript

I have code that looks like this:
function getTopicOptions(accountID, showTitles, showSelectGroup) {
"use strict";
var accountID = store.getItem('AccountID');
showTitles = (showTitles !== 'undefined') ? showTitles : 'Y';
showSelectGroup = (showSelectGroup !== 'undefined') ? showSelectGroup : 'Y';
The idea is that if showTitle and showSelectGroup are not supplied then they will get the default of "Y".
Is there a way do this with function overloading or a way to have the function parameters checked (jslint?) or a way to simplify what I need to do without the undefined check?

You could do something like this:
showTitles = showTitles || 'Y';
or this would work as well, but is more verbose
showTitles = showTitles ? showTitles : 'Y';
I'm not sure where function overloading comes into your question.

There is popular default params trick:
var showSelectGroup = showSelectGroup || false;
but it depend on param, if it bool ('', 0 and etc) and looks like showSelectGroup || true you can't set false
Also look at:
Set a default parameter value for a JavaScript function [closed]
Is there a better way to do optional function parameters in
Javascript?

EDIT
Following is possible
var functionTest = function(argu) {
argu = argu || 'my argument';//ifargu not passed than 'my argument'
return argu;
};
alert(functionTest());
// browser alerts "my argument"
There is no way of function overloading in javascript ,
But if you dont pass the vlaue in function its became undefined vlaue that means you can call the function like
this function
getTopicOptions(accountID, showTitles, showSelectGroup)
can be called like
getTopicOptions(1);
other two value becomes undefined.

There is an arguments object which is (more or less) an array of all supplied arguments. You can loop through these.
See http://javascriptweblog.wordpress.com/2011/01/18/javascripts-arguments-object-and-beyond/

Related

angular.isDefined() vs obj.hasOwnProperty()

I have an object that may or may not have a status. When using the angular.js framework which would be more appropriate. What are the advantages and disadvantages of both.
var checkStatus = function(item){
if(angular.isDefined(item.status){
//do something
}
//VS.
if(item.hasOwnProperty('status')){
//do something
}
}
checkStatus(item);
angular.isDefined only test if the value is undefined :
function isDefined(value){return typeof value !== 'undefined';}
Object.hasOwnProperty test if the value is a direct one and not an inherited one.
For example :
var test = {};
angular.isDefined(test.toString); // true
test.hasOwnProperty('toString'); // false
info : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

Cache is not defined error

function example(str) {
var cache = ( str != "" ) ? str : null;
}
example("something");
alert(cache); // cache is not defined
On alert, it says cache is not defined. How to make it so that after calling a function, cache will be saved and I could invoke it like alert(cache).
The variable 'cache' is defined in the function example and not outside that scope so alert does not have access to it. Please look at other similar questions, example: https://stackoverflow.com/questions/22113894/variables-from-anonymous-function/22114051#22114051 ; not 10 minutes ago. I would also recommend reading on Javascript especially how variable scope works. It is very similar to most programming languages but funky in a couple other, ex: http://msdn.microsoft.com/en-us/library/bzt2dkta(v=vs.94).aspx
Not recommended, but a quick answer is:
var cache;
function example(str) {
cache = ( str != "" ) ? str : null;
}
example("something");
alert(cache);
cache is a local variable to example function. I suggest to use a namespace instead of a global variable. If it wont be a global variable, be free to use a classic var declaration.
so:
var app = app || {}; //define namespace
app.cache = "";
function example(str) {
app.cache = str != "" ? str : null;
//i guess it should equal to:
// cache = str ? str : null;
}
console.log(str); //similar to alert, but logs in developers tool (chrome) or firebug(FFx)
ps: I suggest the use of console.log() (or debug) instead of alert(). It's more comfortable than alert()
Self-memorizing functions
Memorization is the process of building a function that’s capable of
remembering its previously computed values. This can markedly increase
performance by avoiding needless complex computations that have
already been performed.
function foo(str) {
if (!foo.cache) {
foo.cache = ( typeof str !== undefined ) ? str : null;
}
}
foo("something");
alert(foo.cache);
Define cache outside function exmaple()
var cache;
function example(str) {
cache = ( str != "" ) ? str : null;
}
When you define inside the function it's scope would be finished inside it, so you can not access cache from outside of function in your case.

Restoring a nullified function back in JavaScript

I was simply practicing a little bit of JavaScript. My goal was to create a function that can call another function with the .invoke() until .revoke() is called, which then nullifies the function.
Later on, I've added .porcupine() which was, in theory, supposed to take the firstly invoked function (in this case, alert()) and then reapply it to the original "temp". The issue is, though, after being revoked temp becomes unknown, therefore it can not call anything anymore. Is there something very obvious to this that I'm missing out or will the solution have to be fairly messy?
var denullifier;
function revocable(unary) {
if (denullifier === null)
denullifier = unary;
return {
invoke: function(x) {
return unary(x);
},
revoke: function() {
var nullifier = unary;
unary = null;
return nullifier.apply(this, arguments);
},
porcupine: function() {
unary = denullifier;
return unary.apply(denullifier, arguments);
}
};
};
console.log('----------');
temp = revocable(alert);
temp.invoke(7); ///alerts 7
temp.revoke();
temp.porcupine(); //exception
temp.invoke(7); //doesn't get here
I don't quite understand what you're doing, but there are a few problems with your code.
if (denullifier === null)
denullifier = unary;
denullifier is not null here, it's undefined - so the condition isn't met.
return nullifier.apply(this, arguments);
You can't call alert this way, the first param must be null or window.
return unary.apply(denullifier, arguments);
The same.
This is your problem:
var denullifier;
function revocable(unary) {
if (denullifier === null)
denullifier = unary;
denullifier is undefined when declared without a value. However, you are checking for type-strict equality with null, which will be false, so denullifier is never set and porcupine is not able to restore the unary function.
I'd suggest:
Use == instead of === to get equality with undefined
Even better, use typeof denullifier != "function"
Or, (although I don't know your design) you should not make denullifier a global, static variable that will be shared amongst revocable instances, but instead make it instance-specific by putting the declaration inside the function body.

Correctly way to find some variable with 2 case

I want to find some variable from 2 different element patterns.
var something = $('.class').attr('data-something');
if(typeof something === 'undefined') {
var something = $('.class').attr('data-another');
}
if(typeof something != 'undefined') {
// do action...
console.log(something);
}
I just want to get some data from attr data-someting="mydata"
And if data-someting="mydata" not found so find a data form data-another
Then do action....
Im doing right ? or another correctly way to do better ?
Whats about Try Catch ?
Some browsers will have it undefined while some will return false. So, here is a more robust version:
if (typeof something === 'undefined' || something === false) {
// try another attribute
} else {
// do your stuff
}
Update:
Hm, accroding to the doc:
As of jQuery 1.6, the .attr() method returns undefined for attributes
that have not been set.
So, probably, they are explicitly ensuring this themselves as of 1.6 and my information about false is outdated. In this case your own code is perfectly correct.
You can/should access data properties using $.data();
e.g
var something = $('.class').data('something');
var something = $('.class').attr('data-something') || $('.class').attr('data-another')
This will do for both undefined and false values

Testing if value is a function

I need to test whether the value of a form's onsubmit is a function. The format is typically onsubmit="return valid();". Is there a way to tell if this is a function, and if it's callable? Using typeof just returns that it's a string, which doesn't help me much.
EDIT: Of course, I understand that "return valid();" is a string. I've replaced it down to "valid();", and even "valid()". I want to know if either of those is a function.
EDIT: Here's some code, which may help explain my problem:
$("a.button").parents("form").submit(function() {
var submit_function = $("a.button").parents("form").attr("onsubmit");
if ( submit_function && typeof( submit_function.replace(/return /,"") ) == 'function' ) {
return eval(submit_function.replace(/return /,""));
} else {
alert("onSubmit is not a function.\n\nIs the script included?"); return false;
}
} );
EDIT 2: Here's the new code. It seems that I still have to use an eval, because calling form.submit() doesn't fire existing onsubmits.
var formObj = $("a.button").parents("form");
formObj.submit(function() {
if ( formObj[0].onsubmit && typeof( formObj.onsubmit ) == 'function' ) {
return eval(formObj.attr("onsubmit").replace(/return /,""));
} else {
alert("onSubmit is not a function.\n\nIs the script included?");
return false;
}
} );
Suggestions on possibly how to do this better?
I'm replacing a submit button with an
anchor link. Since calling
form.submit() does not activate
onsubmit's, I'm finding it, and
eval()ing it myself. But I'd like to
check if the function exists before
just eval()ing what's there. – gms8994
<script type="text/javascript">
function onsubmitHandler() {
alert('running onsubmit handler');
return true;
}
function testOnsubmitAndSubmit(f) {
if (typeof f.onsubmit === 'function') {
// onsubmit is executable, test the return value
if (f.onsubmit()) {
// onsubmit returns true, submit the form
f.submit();
}
}
}
</script>
<form name="theForm" onsubmit="return onsubmitHandler();">
<a href="#" onclick="
testOnsubmitAndSubmit(document.forms['theForm']);
return false;
"></a>
</form>
EDIT : missing parameter f in function testOnsubmitAndSubmit
The above should work regardless of whether you assign the onsubmit HTML attribute or assign it in JavaScript:
document.forms['theForm'].onsubmit = onsubmitHandler;
Try
if (this.onsubmit instanceof Function) {
// do stuff;
}
You could simply use the typeof operator along with a ternary operator for short:
onsubmit="return typeof valid =='function' ? valid() : true;"
If it is a function we call it and return it's return value, otherwise just return true
Edit:
I'm not quite sure what you really want to do, but I'll try to explain what might be happening.
When you declare your onsubmit code within your html, it gets turned into a function and thus its callable from the JavaScript "world". That means that those two methods are equivalent:
HTML: <form onsubmit="return valid();" />
JavaScript: myForm.onsubmit = function() { return valid(); };
These two will be both functions and both will be callable. You can test any of those using the typeof operator which should yeld the same result: "function".
Now if you assign a string to the "onsubmit" property via JavaScript, it will remain a string, hence not callable. Notice that if you apply the typeof operator against it, you'll get "string" instead of "function".
I hope this might clarify a few things. Then again, if you want to know if such property (or any identifier for the matter) is a function and callable, the typeof operator should do the trick. Although I'm not sure if it works properly across multiple frames.
Cheers
What browser are you using?
alert(typeof document.getElementById('myform').onsubmit);
This gives me "function" in IE7 and FireFox.
using a string based variable as example and making use instanceof Function
You register the function..assign the variable...check the variable is the name of function...do pre-process... assign the function to new var...then call the function.
function callMe(){
alert('You rang?');
}
var value = 'callMe';
if (window[value] instanceof Function) {
// do pre-process stuff
// FYI the function has not actually been called yet
console.log('callable function');
//now call function
var fn = window[value];
fn();
}
Make sure you are calling typeof on the actual function, not a string literal:
function x() {
console.log("hi");
}
typeof "x"; // returns "string"
typeof x; // returns "function"
You can try modifying this technique to suit your needs:
function isFunction() {
var functionName = window.prompt('Function name: ');
var isDefined = eval('(typeof ' + functionName + '==\'function\');');
if (isDefined)
eval(functionName + '();');
else
alert('Function ' + functionName + ' does not exist');
}
function anotherFunction() {
alert('message from another function.');
}
form.onsubmit will always be a function when defined as an attribute of HTML the form element. It's some sort of anonymous function attached to an HTML element, which has the this pointer bound to that FORM element and also has a parameter named event which will contain data about the submit event.
Under these circumstances I don't understand how you got a string as a result of a typeof operation. You should give more details, better some code.
Edit (as a response to your second edit):
I believe the handler attached to the HTML attribute will execute regardless of the above code. Further more, you could try to stop it somehow, but, it appears that FF 3, IE 8, Chrome 2 and Opera 9 are executing the HTML attribute handler in the first place and then the one attached (I didn't tested with jQuery though, but with addEventListener and attachEvent). So... what are you trying to accomplish exactly?
By the way, your code isn't working because your regular expression will extract the string "valid();", which is definitely not a function.
If it's a string, you could assume / hope it's always of the form
return SomeFunction(arguments);
parse for the function name, and then see if that function is defined using
if (window[functionName]) {
// do stuff
}
Isn't typeof xxx === 'function' the best and the fastest?
I made an bench in wich you can try it out, compared to instanceof and _underscore
Its just seems to be faster than instanceof (using chrome)
It won't trow an error if the variable is not defined
Here a bench: https://jsbench.me/qnkf076cqb/1
Checking the call method on the value seems to be a good enough test. e.g., val.call && val()
> a = () => {}
[Function: a]
> function b() {}
undefined
> c = function(){}
[Function: c]
> d = 2
2
> e = []
[]
> f = {}
{}
> a.call
[Function: call]
> b.call
[Function: call]
> c.call
[Function: call]
> d.call
undefined
> e.call
undefined
> f.call
undefined
Note: Except when it's a class.
Well, "return valid();" is a string, so that's correct.
If you want to check if it has a function attached instead, you could try this:
formId.onsubmit = function (){ /* */ }
if(typeof formId.onsubmit == "function"){
alert("it's a function!");
}
You can always use one of the typeOf functions on JavaScript blogs such as Chris West's. Using a definition such as the following for the typeOf() function would work:
function typeOf(o){return {}.toString.call(o).slice(8,-1)}
This function (which is declared in the global namespace, can be used like this:
alert("onsubmit is a " + typeOf(elem.onsubmit));
If it is a function, "Function" will be returned. If it is a string, "String" will be returned. Other possible values are shown here.
I think the source of confusion is the distinction between a node's attribute and the corresponding property.
You're using:
$("a.button").parents("form").attr("onsubmit")
You're directly reading the onsubmit attribute's value (which must be a string). Instead, you should access the onsubmit property of the node:
$("a.button").parents("form").prop("onsubmit")
Here's a quick test:
<form id="form1" action="foo1.htm" onsubmit="return valid()"></form>
<script>
window.onload = function () {
var form1 = document.getElementById("form1");
function log(s) {
document.write("<div>" + s + "</div>");
}
function info(v) {
return "(" + typeof v + ") " + v;
}
log("form1 onsubmit property: " + info(form1.onsubmit));
log("form1 onsubmit attribute: " + info(form1.getAttribute("onsubmit")));
};
</script>
This yields:
form1 onsubmit property: (function) function onsubmit(event) { return valid(); }
form1 onsubmit attribute: (string) return valid()
// This should be a function, because in certain JavaScript engines (V8, for
// example, try block kills many optimizations).
function isFunction(func) {
// For some reason, function constructor doesn't accept anonymous functions.
// Also, this check finds callable objects that aren't function (such as,
// regular expressions in old WebKit versions), as according to EcmaScript
// specification, any callable object should have typeof set to function.
if (typeof func === 'function')
return true
// If the function isn't a string, it's probably good idea to return false,
// as eval cannot process values that aren't strings.
if (typeof func !== 'string')
return false
// So, the value is a string. Try creating a function, in order to detect
// syntax error.
try {
// Create a function with string func, in order to detect whatever it's
// an actual function. Unlike examples with eval, it should be actually
// safe to use with any string (provided you don't call returned value).
Function(func)
return true
}
catch (e) {
// While usually only SyntaxError could be thrown (unless somebody
// modified definition of something used in this function, like
// SyntaxError or Function, it's better to prepare for unexpected.
if (!(e instanceof SyntaxError)) {
throw e
}
return false
}
}
if ( window.onsubmit ) {
//
} else {
alert("Function does not exist.");
}
Beware that es6 class is also a function but not callable
class C {}
typeof C === "function" // true
C instanceof Function // true
C() // error
C.call() // error
new C() // okay
new C // okay
A simple check like this will let you know if it exists/defined:
if (this.onsubmit)
{
// do stuff;
}

Categories

Resources