unexpected call to a function in Javascript - javascript

I'm not really good at javascript so I'm here asking.
Below is a sample code.
<html>
<head>
<script>
function test(one)
{
alert('surprise! first function with one parameter');
}
function test(one,two)
{
alert('expected: second function with two parameters');
}
</script>
</head>
<body onload="javascript:test('first')">
</body>
</html>
Questions:
I expected that that 'surprise! first function with one parameter' would be then alerted onload because I call the function with one parameter only. To my surprise it alerted in the second function.
Can someone explain this to me why?
and how can I make my way around it?

Javascript doesn't support method overloading;
It just overwrites the function so the last one will get called every time.
A way around it is just to make 1 function and put some conditions in there to check if the variables are set.

You declare twice the function test. The 2nd one overwrite the first definition.

In JavaScript overloaded functions are not allowed. so in this case the second function overrides the first one and therefore you always see this result.
A work around for this is to check the values of the parameters:
function test(one,two)
{
if(two)
alert('expected: second function with two parameters');
else
alert('surprise! first function with one parameter');
}

In javascript the parameters for a function aren't required. You'd want to check to see if the parameter is undefined before using it.
If used this before in order to implement getter/setter type functionality in javascript similar to below:
var _pageSize;
function pageSize(value) {
if (value) {
_pageSize = value;
}
else {
return _pageSize;
}
}
You can then use the pageSize method to both get and set the page size like below:
if (pageSize() < 15) {
pageSize(15)
}

Ah, Javascript doesn't do polymorphism like that. It does have an arguments collection that you can look in and then do the right thing given the inputs..
stuff like:
function calcAverage()
{
var sum = 0
for(var i=0; i<arguments.length; i++)
sum = sum + arguments[i]
var average = sum/arguments.length
return average
}
document.write("Average = " + calcAverage(400, 600, 83))

When calling such function:
function test(one,two)
With only one parameter, the argument "two" will have special type: undefined.
Any attempt to access the variable two will fail with "two is undefined" error, to avoid such error use the typeof command:
function test(one,two)
{
if (typeof two == "undefined") {
//give default value
two = "default value here";
}
...
}

Related

Javascript invalid function? what I am missing?

I used textwrangler to write my codes to better show my codes and progression. On the comment section of my codes, I wrote my concern and the purpose of my codes.
var pets = ["pet1", "pet2", "pet3"]
function displayPets() {
console.log("my pets:", pets);
}
// addPets() will name all new pets "new pets" ie ("pet1", "pet2", "pet3", "new pets"....)
function addPets() {
pets.push("new pet");
displayPets();
}
/ try different method using the parameter
function addPets(petName) {
pets.push("petName");
displayPets();
}
// pets.push isn't not a function
addPets(brutus)
Will in the different and the first function you are using the same name and you may see another error(not basically error its just a bug) that you can not take the input from the perimeter that is because you are push an string not the variable in the different method and when you are calling the different function you are not putting an string that will also cause an error, If you are not understand hoping the below code can help
var pets = ["pet1", "pet2", "pet3"]
function displayPets() {
console.log("my pets:", pets);
}
// addPets() will name all new pets "new pets" ie ("pet1", "pet2", "pet3", "new pets"....)
function addPets() {
pets.push("new pehttps://stackoverflow.com/questions/44062303/javascript-invalid-function-what-i-am-missing#t");
displayPets();
}
// try different method using the parameter
function addPetsDifferentMethod(petName) {
pets.push(petName);
displayPets();
}
// pets.push isn't not a function
addPetsDifferentMethod("brutes")
There are no overload functions in JS. The last one will alway be called. we have to write the function defeniton to act like Overloaded function.
fiddle
function addPets(petName){
if(petName){ // if petname is present
pets.push(petName)
}
else{
pets.push("newPet");
}
displayPets();
}

Javascript Function Calls: Regular call vs Call vs Bind Call

My question is simple:
I'm passing a function to some other function to be call later (sample callback function), the question is when, why and what is the best practice to do it.
Sample:
I have the xxx() function, and I have to pass it, as I show you below in the window.onload event.
What is the best practice and why? There is any performance aspect or why should I choose to use call or bind to call this function
function xxx(text)
{
var div = document.createElement("div");
div.innerHTML = text + " - this: " + this.toString();
document.body.appendChild(div)
}
function callFunction(func)
{
func("callFunction");
}
function callUsingCall(func)
{
func.call(this, ["callUsingCall"]);
}
function callUsingBind(func)
{
func.call(this, ["callUsingCall"]);
}
window.onload = function(){
callFunction(xxx);
callUsingCall(xxx);
callUsingBind(xxx.bind(document));
}
Thank you,
Sebastian P.
I don't think there's any "best" practise.
You use call if the function you're calling cares what this is.
You use bind if you want to ensure that the function can only be called with the specified value of this.
[There's some overhead to both, i.e. at least one depth of function calls / scope]
Otherwise you just call the function.
Simples :)
The this object is the context of the function. It's like you make a machine that something for you, and the this object would be the place that the machine works in, like your house. You can move it as you like.
We have 4 ways setting this objects.
Calling the function that is not a method:
fn(someArguments)
This way the this object is set to null or probably the window object.
Calling the function as a method:
someObject.fn(someArguments)
In this case the this object will point to someObject and it's mutable.
Calling with call or apply methods of the function.
fn.call(anotherObject, someArguments)
someObject.call(anotherObject, someArguments)
someObject.apply(anotherObject, [someArguments])
In this case the this object will point to someObject here. You are forcing it to have another context, when calling it.
Binding a the function
var fn2 = fn.bind(anotherObject, someArguments)
This will create another function that is binded to that this object we gave it(anotherObject). No matter how you call it, the this object is going to be the same.
Use Cases
Now you can do some tricky stuff knowing this. The reason that why we have it here(I think it came first from C++) is that methods of an object need to access to their parent. The this object provides the access.
var coolObject = {
points : ['People are amazing'],
addPoint : function (p) { this.points.push(p) }
}
So if you do the following it won't work:
var addPoint = coolObject.addPoint;
addPoint('This will result in an error');
The error will be thrown because the this object is not our coolObject anymore and doesn't have the points property. So at times like this, you can something like this:
var addPoint = coolObject.addPoint;
addPoint.call({points : []}, 'This is pointless');
This is pointless, but the function will work, even the this object is not what its supposed to be.
var anotherCoolObject = {
points : ['Im a thief!'],
addPoint : coolObject.addPoint
}
anotherCoolObject.addPoint('THIS IS CALL STEALING');
Still the function will work if you call it like that, since the this object will point to anotherCoolObject which has the points property.
The most popular use case I've seen is slicing the arguments object:
function returnHalf() {
return [].slice.call(arguments, 0, arguments.length / 2);
}
returnHalf('Half', 'is', 'not', 'awesome');
// >> [Half', 'is']
So you see, arguments object is not an instanceof array. If we do arguments.slice(...) then you're gonna be killed by the compiler. But here we use the array's method on arguments object, since it's array like.
Sometimes you don't want your function context to be changed or you wanna add your own arguments, you use bind.
For example when you add a listener for an event with jquery, when jquery calls your function, the this object will be the element. But sometimes you wanna do tricky stuff and change it:
var myElement = {
init : function () {
$(this.element).click(this.listener.bind(this));
},
view : "<li>${Name}</li>",
name : 'ed',
element : $('#myelement'),
listener : function () {
this.element.append($.tmpl( this.view, this ));
}
}
myElement.init();
So here, you bind it to the myElement, so you can have access to the object properties to render the view. Another examples would be the following:
for (var i = 0; i < 10; i++) {
setTimeout(function () {console.log(i)}, 10)
}
// All of them will be 10.
for (var i = 0; i < 10; i++) {
setTimeout((function () {console.log(this.i)}).bind({ i : i }, 10)
}
If you have put an asynchronous function call in a loop, by the time the callback is called, the loop is finished, and the counter have reached the end, you can use bind to cleanly bind the current counter to your callback.
Another good use case of it, that I use a lot is when passing my functions with arguments to async module, without creating closures.
async.parallel({
writeFile : function (cb) {
fs.writeFile('lolz.txt', someData, cb);
},
writeFile2 : function (cb) {
fs.writeFile('lolz2.txt', someData, cb);
}
}, function (err){
console.log('finished')
});
async.parallel({
writeFile : fs.writeFile.bind(fs, 'lolz.txt', someData),
writeFile2 : fs.writeFile.bind(fs, 'lol2z.txt', someData),
}, function (err){
console.log('finished')
});
These two implementations are identical.
Performance
Just check these out:
http://jsperf.com/bind-vs-call2
http://jsperf.com/js-bind-vs-closure/2
http://jsperf.com/call-vs-closure-to-pass-scope/10
bind has a big performance overhead comparing to other types of calling, but make sure you don't sacrifice performance with maintainability with pre-mature optimizations.
Also you can have a look at this article.

Having a closure issue. Can't seem to resolve it. Please advise

I have this code:
_trackit: function(){
for(var key in this.items.sublinks){
switch(key){
case 'shoes':
for(var innerkey in this.items.sublinks[key]){
(function(){
$(innerkey).observe('click', (function(e){
Event.stop(e);
someClass.click_link( this.items.sublinks[key][innerkey],false)
}));
)(this);
}
break;
}
}
}
The hash I am passing in has a size of 2. But as you would guess both of the links (since the hash maps to links), are passing the last hash value to come through (someClass.click_link <- in here this value, this.item.sublinks[key][innerkey]).
I've tried using an innerfuction etc... but something is messing up. If I go to "inner function deep", then this.items returns undefined.
Any help?
Since you're passing this in as an argument, you just need to create a parameter for it — call it, say, _this — and then you can refer to _this instead of this inside the function:
(function(_this, innerkey){
$(innerkey).observe('click', (function(e){
Event.stop(e);
someClass.click_link( _this.items.sublinks[key][innerkey],false)
}));
)(this, innerkey);
(There are other ways as well, but the above seems to be the way you were going for when you passed this in as an argument? And it's a perfectly respectable way to do it.)
Edited to add: Per Rob W's comment, I've edited the above to add innerkey as a parameter as well, since otherwise the inner function(e){...} expression will refer to the same innerkey variable as the outer function — a variable which, as a loop variable, is likely to have changed by the time the inner function actually runs. Passing it as a parameter gives the inner expression a new innerkey variable that's equal to what innerkey was when the inner function was created.
As others mentioned, you need to have an argument to receive the "this" you are passing. You will also need to pass copies of the "key" and "innerkey" variables, in order to avoid the closures inside for loops bug.
var make_event_listener = function(that, key, innerKey){
return function(e){
Event.stop(e);
someClass.click_link( that.items.sublinks[key][innerkey], false)
};
};
//...
for(var innerkey in this.items.sublinks[key]){
$(innerkey).observe('click', make_event_listener(this, key, innerKey) );
}
//...
OF course, you can use an anonymous version of make_event_listener instead but I find this way more readable.
The second call to "this" references the actual element being clicked. Change it to:
_trackit: function () {
var self = this;
for (var key in this.items.sublinks) {
switch (key) {
case 'shoes':
for (var innerkey in this.items.sublinks[key]) {
(function () {
$(innerkey).observe('click', (function (e) {
Event.stop(e);
someClass.click_link(self.items.sublinks[key][innerkey], false)
}));)(this);
}
break;
}
}
}
}

How to execute a JavaScript function when I send its name as string dynamically without parameters

I want execute JavaScript function which the name is coming as a string dynamically.
I don't need to pass any parameters while executing the function.
Please can any one guide me how to achieve this?
one simple way
eval("SomeFunction()");
or
var funcName = "SomeFunction";
var func == window[funcName];
func();
dangerous but you could use eval(method_name+"()")
are you talking about ´eval()´??
var foo = "alert('bar')";
eval(foo);
Hope this helps;
function a() {
console.log('yeah!');
}
var funcName = 'a'; // get function name
this[funcName]();
If the function is global, you should do window[funcName]() in browser.
Using eval is the worst way imaginable. Avoid that at all costs.
You can use window[functionname]() like this:
function myfunction() {
alert('test');
}
var functionname = 'myfunction';
window[functionname]();
This way you can optionally add arguments as well
Perhaps a safer way is to do something like this (pseudo code only here):
function executer(functionName)
{
if (functionName === "blammo")
{
blammo();
}
else if (functionName === "kapow")
{
kapow();
}
else // unrecognized function name
{
// do something.
}
You might use a switch statement for this (it seems like a better construct):
switch (functionName)
{
case "blammo":
blammo();
break;
case "kapow":
kapow();
break;
default:
// unrecognized function name.
}
You can optimize this by creating an array of function names, searching the array for the desired function name, then executing the value in the array.

Send a variable to a variable of a function?

Let's say I have a function and one of the parameters is for the name of the target variable.. Would it be possible for me to send a variable to the function like this:
function otherfunction(input){
...
}
function test {target) {
var x = 1;
target(x);
}
test(otherfunction);
The problem I have is that I'm making a greasemonkey script and one of the variable I need can't be returned from the function due to a limitation.. So this would be the alternative. I just don't know how to get it to work.. Any help would be much appreciated!!
Your example (almost) works:
function otherfunction(input){
alert(input);
}
function test(target) {
if(typeof target !== 'function') {
alert('target is not a function!');
return;
}
target(1); //invokes the passed-in function, passing in 1
}
test(otherfunction); //alerts 1
//You can also do it with an anonymous function too:
test(function(arg) {
alert(arg * 5);
}); //alerts 5
jsFiddle example

Categories

Resources