Подтвердить что ты не робот

Перегрузка метода в Javascript

Я использую перегрузку метода, как показано ниже в моем Javascript-коде.

function somefunction()
{
    //1st function
}

function somefunction(a)
{
   //2nd function
}

function somefunction(a,b)
{
   //3rd function
}

somefunction(); // function call goes here

Я не понимаю, что если я называю somefunction(), javascript должен вызывать 1-ю функцию, но проблема в том, что javascript фактически вызывает 3-ей функцию. Почему это? Как я могу назвать 1-ю и 2-ю функции? Что является причиной этого? Есть ли способ реализовать перегрузку метода в Javascript? Что такое отраслевой стандарт?

4b9b3361

Ответ 1

JavaScript не поддерживает перегрузку методов (как в Java или аналогичную), ваша третья функция перезаписывает предыдущие объявления.

Вместо этого он поддерживает переменные аргументы через объект arguments. Вы могли бы сделать

function somefunction(a, b) {
    if (arguments.length == 0) { // a, b are undefined
        // 1st body
    } else if (arguments.length == 1) { // b is undefined
        // 2nd body
    } else if (arguments.length == 2) { // both have values
        // 3rd body
    } // else throw new SyntaxError?
}

Вы также можете просто проверить typeof a == "undefined" и т.д., это позволит вызвать somefunction(undefined), где arguments.length - 1. Это может позволить более простой вызов с различными параметрами, например, когда у вас есть возможно-пустые переменные.

Ответ 2

Вы просто стираете переменную somefunction с каждым новым объявлением.

Это эквивалентно

   window.somefunction = function(...
   window.somefunction = function(...
   window.somefunction = function(...

Javascript не предлагает перегрузки методов.

Правильный способ:

  • чтобы определить третью функцию и проверить, какие параметры определены
  • передать только один объект, содержащий параметры (который не совсем другой, но более чистый).

Ответ 3

JS передаст undefined на любые параметры, которые не предусмотрены. Если вы хотите что-то вроде перегрузки, вам нужно сделать что-то похожее на код ниже:

function someFunction(a, b) {
    if (typeof a === 'undefined') {
        // Do the 0-parameter logic
    } else if (typeof b === 'undefined') {
        // Do the 1-parameter logic
    } else {
        // Do the 2-parameter logic
    }
}

Ответ 4

Вы не можете перегружать методы в JavaScript. В javascript функции хранятся в переменных. Глобальные переменные хранятся в объекте окна. Вы можете иметь только одно свойство для одного объекта с одним и тем же именем (хэш исключающего ключа).

Что вы можете сделать, определяется определение с большинством параметров и проверяет, сколько их было передано.

function Test(a, b, c)
{
    if(typeof a == 'undefined') 
    {
        a = 1;
    }

    if(typeof b == 'undefined') 
    {
        b = "hi";
    }

    if(typeof c == 'undefined') 
    {
        c = Date.Now;
    }
}

Теперь, если я вызову Test(), он будет действовать так, как если бы я назвал Test(1, "hi", Date.Now)

Ответ 5

В JavaScript нет реальной перегрузки функций, поскольку она позволяет передавать любое количество параметров любого типа. наилучшей практикой было бы сделать функцию  как: MyFunc (вариант)

{
// with opt = {'arg1':'a1','arg2':2, etc}, then check your opt inside of the function
}

Ответ 6

Я попытался разработать элегантное решение этой проблемы, описанной здесь здесь. И здесь вы можете найти демо здесь. Использование выглядит следующим образом:

var out = def({
    'int': function(a) {
        alert('Here is int '+a);
    },

    'float': function(a) {
        alert('Here is float '+a);
    },

    'string': function(a) {
        alert('Here is string '+a);
    },

    'int,string': function(a, b) {
        alert('Here is an int '+a+' and a string '+b);
    },
    'default': function(obj) {
        alert('Here is some other value '+ obj);
    }

});

out('ten');
out(1);
out(2, 'robot');
out(2.5);
out(true);

Используемые методы:

var def = function(functions, parent) {
 return function() {
    var types = [];
    var args = [];
    eachArg(arguments, function(i, elem) {
        args.push(elem);
        types.push(whatis(elem));
    });
    if(functions.hasOwnProperty(types.join())) {
        return functions[types.join()].apply(parent, args);
    } else {
        if (typeof functions === 'function')
            return functions.apply(parent, args);
        if (functions.hasOwnProperty('default'))
            return functions['default'].apply(parent, args);        
    }
  };
};

var eachArg = function(args, fn) {
 var i = 0;
 while (args.hasOwnProperty(i)) {
    if(fn !== undefined)
        fn(i, args[i]);
    i++;
 }
 return i-1;
};

var whatis = function(val) {

 if(val === undefined)
    return 'undefined';
 if(val === null)
    return 'null';

 var type = typeof val;

 if(type === 'object') {
    if(val.hasOwnProperty('length') && val.hasOwnProperty('push'))
        return 'array';
    if(val.hasOwnProperty('getDate') && val.hasOwnProperty('toLocaleTimeString'))
        return 'date';
    if(val.hasOwnProperty('toExponential'))
        type = 'number';
    if(val.hasOwnProperty('substring') && val.hasOwnProperty('length'))
        return 'string';
 }

 if(type === 'number') {
    if(val.toString().indexOf('.') > 0)
        return 'float';
    else
        return 'int';
 }

 return type;
};

Ответ 7

  Что я не понимаю, так это то, что если я вызываю somefunction(), javascript должен вызывать первую функцию, но проблема в том, что javascript фактически вызывает третью функцию.

Это ожидаемое поведение.

Почему это так?

Проблема в том, что JavaScript НЕ поддерживает перегрузку методов. Таким образом, если он видит/анализирует две или более функций с одинаковыми именами, он просто учитывает последнюю определенную функцию и перезаписывает предыдущие.

Почему это? Как я могу вызвать 1-ю и 2-ю функцию? В чем причина этого?

Один из способов, который, на мой взгляд, подходит для большинства случаев, заключается в следующем -

Допустим, у вас есть метод

function foo(x)
{
} 

Вместо перегрузки метода , что невозможно в javascript, вы можете определить новый метод

fooNew(x,y,z)
{
}

а затем измените первую функцию следующим образом -

function foo(x)
{
  if(arguments.length==2)
  {
     return fooNew(arguments[0],  arguments[1]);
  }
} 

Если у вас много таких перегруженных методов, рассмотрите возможность использования switch, а не просто операторов if-else.

Есть ли правильный способ сделать перегрузку метода? Какой отраслевой стандарт?

Не существует стандарта как такового или более проверенного метода для перегрузки методов в javascript. Нужно делать то, что лучше всего подходит для их программирования. Я бы сказал, достаточно простого переключения длины аргументов с проверкой типа, чтобы оно не было неопределенным.

Ответ 8

Объект

arguments используется для создания метода перегрузки как концепция.

аргументы - это особый тип объекта, доступный только внутри контекста выполнения функций.

Свойство

arguments.length используется для идентификации количества параметров, переданных в функцию.

Вы можете лучше использовать функции первого класса для создания перегрузки поддельных методов. Полная концепция объясняется на моем собственном сайте: Функции перегрузки в JavaScript

Ответ 9

Перегрузка метода напрямую не поддерживается в JavaScript. Вот пример, как вы можете достичь чего-то очень похожего, как показано ниже:

function overloadMethod(object, name, fn){

            if(!object._overload){
            object._overload = {};
            }

            if(!object._overload[name]){
            object._overload[name] = {};
            }

            if(!object._overload[name][fn.length]){
            object._overload[name][fn.length] = fn;
            }

              object[name] = function() {
                        if(this._overload[name][arguments.length])
                        return this._overload[name][arguments.length].apply(this, arguments);
              };
}

function Students(){
  overloadMethod(this, "find", function(){
            // Find a student by name
  });

  overloadMethod(this, "find", function(first, last){
            // Find a student by first and last name
  });

}

var students = new Students();
students.find(); // Finds all
students.find("Rahul"); // Finds students by name
students.find("Rahul", "Mhatre"); // Finds users by first and last name

источник: источник