Why can I create two functions with the same Javascript signature?

Asked

Viewed 1,249 times

36

I’m having doubts about a certain issue in Javascript, suppose the following scenario below:

function teste() {
  console.log("teste1");
}

function teste() {
  console.log("teste2");
}

teste();

In that case I realized that my method teste() it was kind of overwritten, I don’t know if that’s really what happens, when we call the same just the teste2 that is displayed. Now the doubts regarding that:

  1. This is really the expected behavior when we declare 2 methods with the same name and parameters in js, it will always override and will prevail the last declared?
  2. Is there any explanation for this behavior, if yes what it is explanation?
  3. Is there any way to do it that causes some mistake or something if someone makes this mistake and declares 2 methods with the same name and parameters?
  4. In case 3 has any way of doing, what to do if the functions are in different js files?
  • This doubt must have arisen because you are used to typed programming, in which there can be "equal" methods with different parameters.

  • 2
  • @Virgilionovic could be my mistake, function adiciona(produto) {
 console.log(produto);
}
function adiciona(produto, categoria) {
 console.log(produto, categoria);
}

adiciona(1);
adiciona(1, 2); did not work, at least the article hinted that it works :/ (tested in Chrome)

  • Opa @Guilhermenascimento I was curious not know this issue in Javascript that is not my strong, but, boy I did not really test the validity of this link, I will test it and maybe some charitable soul can guide us on this ... ! Any news I tell you ... !!!

  • @Guilhermenascimento The link actually has some coding errors, but by the logic I saw this really ok, the problem is that it would be related to methods of a generated function, I believe that it cannot be applied in window

  • 1

    @Guilhermelautert the test I took was like this (function () {
 function adiciona(produto) {
 console.log("função 1", produto);
 }
 function adiciona(produto, categoria) {
 console.log("função 2", produto, categoria);
 }

 adiciona(1);
 adiciona(1, 2);
 })();, and yet the only result is "função 2".

  • @Guilhermelautert this from Users seems to me the second example, maybe it is fault in the author’s writing and he wants to say that it did not work, I mean the text seems to me confused

  • @Guillhermenascimento see

  • @Guilhermelautert this I came to test yes, what I’m really talking about is how the text was written, it led to a misunderstanding of the situation in the first part, at least to me it seemed this "In Javascript, define a function with the same name to overwrite:" =)

Show 4 more comments

3 answers

26

I believe you have technically already answered "it overwrites", but another is also necessary to understand a feature of function ... (), then I’ll explain a behavior for two ways to declare a function and then I’ll explain this.

In Javascript you can do:

function x() {
}

x();

And setting in the variable:

x = function() {
}
x();

In both cases it will work, however function x() is different from x = function(), for if I do this:

Will work:

x();

function x() {
}

It won’t work, you’ll accuse how undefined:

x();

x = function() {
}

Now the reason, Javascript, as well as many languages, make a "preprocessing" of some things stated, ie when it does this:

x();

function x() {
}

It will occur before run time and will leave all functions that have been declared so function ...() ready for use prior to actual execution, i.e.:

function teste() {
  console.log("teste1");
}

teste();

function teste() {
  console.log("teste2");
}

teste();

See that appears teste2 twice.

Because this occurs

The "Ecmascript engine" (Javascript) of the browser will process its way (it is likely that although internally they work alike they can still work differently to achieve the same result) and it will probably only consider the newer function, that is, at the time of execution the first teste() probably no longer exists.

Even at runtime probably the Javascript is pre-processed, if you look at the following example, even calling x() before instead of displaying oi, will initially display 11:

function x() {
   console.log("oi");
}

var a = 10;

window.onload = function() {
     document.getElementById("test").onclick = function() {
         x();

         function x() {
             console.log(++a);
         }
     };
};
<button id="test">Teste</button>


Note: The link quoted by Virgilo seems to imply that functions with different parameters are supported, but as tests are not possible, see:

function adiciona(a) {
    console.log("função 1 => ", a);
}
function adiciona(b, c) {
    console.log("função 2 => ", b, c);
}

adiciona(1);
adiciona(1, 2);

The example returns:

função 2 =>  1 undefined
função 2 =>  1 2

Alternative

According to this response from Soen, a simple example of checking what you want to call would be:

function foo(a, b, c)
{
  if (arguments.length == 2) {
    console.log("foo 1");
  } else if (arguments.length == 3) {
    console.log("foo 2");
  }
}

foo(1, 2);
foo(1, 2, 3);

And there are more even more complex alternatives to achieve the desired "effect", but I really believe that this is something totally unnecessary, probably at the beginning of languages like you feel some discomfort, but it’s not something you really miss that much.

  • 1

    in the link it says that an additional code has to be implemented in order for the overload, I don’t know how this is good or bad, but I took the test the way it’s on link and it worked, watch: link, now really as described in the question it overwrites getting valid only 1.

  • 1

    @Virgilionovic we have great examples, only I didn’t put something like this because I really think features like this are quite expendable. But your comment is great for future visitors.

  • 1

    @Guilhermenascimento, it is also good to say that (function(){...})(); is used to create a proper scope and thus prevent one function from overwriting another, especially if they are in different files. The downside is that you need to pass any global functions and variables you want within the scope at the beginning and end of this call: (function(minha_biblioteca){...})(minha_biblioteca);

  • And still protects the scope?

  • @Daniel I think I understand, you’re referring to the same variables and not the objects, sorry the confusion, yes the IIFE (Immediately Invoked Function Expression) actually has this goal, in fact the examples should not even contain this, is that by default I always use IIFE in my script, it was force of habit. It has some links from the site itself, then added the answer. Just note that going through argument is just one of the ways to protect the scope. Thank you the/

7

Complementing the answers, if you don’t want your function to be overwritten, and keep its values, you can create them through the const

const teste = function () {
    console.log("Teste1")
}

teste()

var teste = function teste() {
    console.log("Teste2")
}

teste()

Typeerror: const 'test' has already been declared

Execution Time-70ms

var teste = function() {
    console.log("Teste1")
}

teste()

var teste = function() {
    console.log("Teste2")
}

teste()

Teste1

Teste2

Execution Time-48ms

  • I found an excellent suggestion Oracy, exactly as the author of the question asked, congratulations +1

5


Succinct response:

This is the "normal" behavior in Javascript. The language has advanced and today it is already possible to use const to declare constants that cannot be superscripted.

Elongated response:

From the beginning Javascript allows you to overwrite variable and function names, and even assign values to variables without declaring them, "declaring them" in global scope, which has generated bugs difficult to detect.

In modern versions of Javascript much of this has been fixed and for your case the fix is to use const, by assigning a function to a variable.

Thus in Ecmascript 2015 (version 6 of Javascript) exists const that starts a variable that can no longer be over-written without generating build error.

Your questions:

  1. This is really the expected behavior when we declare 2 methods with the same name and parameters in js, it will always override and will prevail the last declared?

Yeah. Unless you use const (which will generate an error if the names are equal). This is the normal behavior, equal to CSS, the last to be declared.

  1. Is there any explanation for this behavior, if yes what it is explanation?

That’s how the language was built, kind of flexible... But it’s being reinforced/corrected in the new versions.

  1. Is there any way to do it that causes some mistake or something if someone makes this mistake and declares 2 methods with the same name and parameters?

Yes, using const the problem is fixed. That is, it gives error if a variable is over-written. In this case you can use:

const teste = function(){
    console.log('teste 1');
}

and if you do it then const teste = outra coisa... compiler gives error and does not run.

  1. In case 3 has any way of doing, what to do if the functions are in different js files?

Then you have to encapsulate things. Either you use CJS, AMD or ES6 modules. There is not yet a universal specification on the part of language, but there are proposals that are under consideration in this regard. If you use the Babel compiler you can use these modules now.

So there are two answers:

With compiled modules you can declare everything in the "global" scope because the module does not share this scope with other files. All variables are encapsulated and the only thing you can export out of the module is via the reserved word exports. An example:

function teste(){
    console.log(1);
}

module.exports = teste;

in that way teste is not visible to other files.

Using native Javascript, where all files share the global space:

Here you have to encapsulate things yourself. The concept is identical but you have to use Iifes to hide variables from each other.

For example:

// ficheiro A
(function(global) {
  function teste() {
    console.log('teste A');
  }

  global.testeA = teste;

})(this);

// ficheiro B
(function(global) {
  function teste(nr) {
    var res = nr * nr;
    console.log('teste B', res);
  }
  global.testeB = teste;

})(this);

testeA();
testeB(17);

Browser other questions tagged

You are not signed in. Login or sign up in order to post.