2010-07-04 3 views
27

Я использую Javascript с jQuery. Я хотел бы реализовать параметры. В C# будет выглядеть примерно так:Как лучше всего реализовать параметры в JavaScript?

/* 
* odp  the object to test 
* error a string that will be filled with the error message if odp is illegal. Undefined otherwise. 
* 
* Returns true if odp is legal. 
*/ 
bool isLegal(odp, out error); 

Каков наилучший способ сделать что-то подобное в JS? Объекты?

function isLegal(odp, errorObj) 
{ 
    // ... 
    errorObj.val = "ODP failed test foo"; 
    return false; 
} 

Firebug сообщает мне, что вышеупомянутый подход будет работать, но есть ли лучший способ?

+0

Ника, я знаю, что это было давно, но я думаю, что у меня наконец есть [ответ] (https://stackoverflow.com/a/48517986/1016343) для вас. Да, вы можете выполнить параметры в JavaScript. – Matt

ответ

13

Я думаю, что это в значительной степени единственный способ (но я не хардкорный JavaScript-программист;)).

То, что вы могли бы также рассмотреть использование функции обратного вызова:

function onError(data) { 
    // do stuff 
} 


function isLegal(odp, cb) { 
    //... 
    if(error) cb(error); 
    return false; 
} 

isLegal(value, onError); 
+1

+1, это более функциональный подход, однако он требует немедленного устранения ошибки. Это также самый распространенный в моем опыте. – gradbot

33

Обратный вызов подход упоминается @Felix Клинг, вероятно, самая лучшая идея, но я также обнаружил, что иногда это легко использовать Javascript объект буквального синтаксиса и просто ваша функция возвращает объект на ошибку:

function mightFail(param) { 
    // ... 
    return didThisFail ? { error: true, msg: "Did not work" } : realResult; 
} 

то при вызове функции:

var result = mightFail("something"); 
if (result.error) alert("It failed: " + result.msg); 

Не фантазия и вряд ли пуленепробиваемая, но, конечно, все в порядке для некоторых простых ситуаций.

+0

+1, Этот подход распространен в JSON-вызовах, но я редко видел его в коде. – gradbot

+1

+1 Мне это нравится ... – Julien

+1

Придя на эту страницу, потому что меня интересовало, как Javascript может обрабатывать или не обрабатывать параметры, я разочарован принятым ответом. Способность иметь определенный тип возврата вместе с одним из многих параметров с определенными типами очень эффективна при программировании очень процедурной логики. К сожалению, с моей крошечной репутацией я не могу проголосовать. –

13

Да, как вы сами упоминали, объекты являются лучшим и единственным способом передачи данных по ссылке в JavaScript. Я хотел бы сохранить свой isLegal функции как таковой, и называть его просто так:

var error = {}; 
isLegal("something", error); 
alert(error.val); 
+1

+1, Этот стиль ближе всех к C#. – gradbot

+0

Это замечательно .. –

3

есть другой способ JS может перейти «из» параметров. но я считаю, что лучшие из них для вашей ситуации уже упоминались.

Массивы также передаются по ссылке, а не по значению. таким образом, как вы можете передать объект функции, а затем установить свойство объекта в функции, а затем вернуться и получить доступ к этому свойству объекта, вы также можете передать массив в функцию, установить некоторые значения массива внутри функции и возвращать и получать доступ к этим значениям вне массива.

поэтому в каждой ситуации вы можете спросить себя: «Является ли массив или объект лучше?»

+0

Хотя это возможно, ради ясности кода в вызывающем коде, я бы рекомендовал @ Pointy ответить: используйте перегруженное возвращаемое значение, поскольку оно немного более четкое. – cmroanirgo

1

Я не буду размещать ни одного code, но что не может быть сделано здесь, в этих ответах должно быть положить рифму по соображениям. Я работаю на родной арене JS, и возникла проблема, что некоторые native API calls нужно преобразовать, потому что мы не можем писать параметры без уродливых позорных хаков.

Это мое решение:

// Functions that return parameter data should be modified to return 
    // an array whose zeroeth member is the return value, all other values 
    // are their respective 1-based parameter index. 

That doesn't mean define and return every parameter. Only the parameters that recieve output.

Причина такого подхода заключается в том, таким образом: Multiple return values может понадобиться для любого количества процедур. Это создает ситуацию, когда объекты с именованными значениями (которые в конечном счете не будут синхронизироваться с лексическим контекстом всех операций), постоянно необходимо запомнить, чтобы надлежащим образом работать с процедурами (процедурами).

Использование метода, предписанного, вы должны знать только what you called и where you should be looking, а не того, чтобы знать, что вы ищете.

Существует также преимущество, заключающееся в том, что «прочный и глупый». Алограммы можно записать, чтобы обернуть вокруг желаемых вызовов процедур, чтобы сделать эту операцию «более прозрачной».

Было бы целесообразно использовать object, function, или array (все из которых являются объектами) в качестве параметра «записи бэк-выход», но я считаю, что если какой-либо постороннее работа должна быть сделана, она должна сделать то, что вы пишете инструментарий, чтобы упростить работу или расширить функциональность.

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

Поздравляем, и удачи.

Я использую webkitgtk3 и подключаю некоторые собственные C-библиотеки proc. поэтому этот проверенный образец кода может, по крайней мере, служить цели иллюстрации.

// ssize_t read(int filedes, void *buf, size_t nbyte) 
SeedValue libc_native_io_read (SeedContext ctx, SeedObject function, SeedObject this_object, gsize argument_count, const SeedValue arguments[], SeedException *exception) { 


    // NOTE: caller is completely responsible for buffering! 

        /* C CODING LOOK AND FEEL */ 


    if (argument_count != 3) { 
     seed_make_exception (ctx, exception, xXx_native_params_invalid, 
      "read expects 3 arguments: filedes, buffer, nbyte: see `man 3 read' for details", 
      argument_count 
     ); return seed_make_undefined (ctx); 
    } 

    gint filedes = seed_value_to_int(ctx, arguments[0], exception); 
    void *buf = seed_value_to_string(ctx, arguments[1], exception); 
    size_t nbyte = seed_value_to_ulong(ctx, arguments[2], exception); 

    SeedValue result[3]; 

    result[0] = seed_value_from_long(ctx, read(filedes, buf, nbyte), exception); 
    result[2] = seed_value_from_binary_string(ctx, buf, nbyte, exception); 

    g_free(buf); 
    return seed_make_array(ctx, result, 3, exception); 

} 
+0

Это отличная идея для возврата параметров в JavaScript. Для меня смысл. – Sunil

1

Ниже приведен подход, который я использую. И это ответ на этот вопрос. Однако код не был протестирован.

function mineCoords(an_x1, an_y1) { 
    this.x1 = an_x1; 
    this.y1 = an_y1; 
} 

function mineTest(an_in_param1, an_in_param2) { 

    // local variables 
    var lo1 = an_in_param1; 
    var lo2 = an_in_param2; 

    // process here lo1 and lo2 and 
    // store result in lo1, lo2 

    // set result object 
    var lo_result = new mineCoords(lo1, lo2); 
    return lo_result; 
} 

var lo_test = mineTest(16.7, 22.4); 
alert('x1 = ' + lo_test.x1.toString() + ', y1 = ' + lo_test.y1.toString()); 
2

Я использую метод обратного вызова (по аналогии с Felix Kling's approach), чтобы имитировать поведение выходных параметров. Мой ответ отличается от Kling тем, что функция обратного вызова действует как замыкание привязки ссылок, а не обработчик.

Этот подход страдает от подробного анонимного синтаксиса функции JavaScript, но тесно воспроизводит семантику параметров с других языков.

function isLegal(odp, out_error) { 
    //... 
    out_error("ODP failed test foo"); // Assign to out parameter. 
    return false; 
} 

var error; 
var success = isLegal(null, function (e) { error = e; }); 

// Invariant: error === "ODP failed test foo". 
0

Обычный подход к конкретному случаю использования вы, изложенные в Javascript, и на самом деле языки наиболее высокого уровня, чтобы полагаться на ошибки (ака исключениями), чтобы дать вам знать, когда произошло что-то из ряда вон выходящим. Невозможно передать тип значения (строки, числа и т. Д.) По ссылке в Javascript.

Я бы просто сделал это. Если вам действительно нужно передать пользовательские данные обратно вызывающей функции, вы можете подклассифицировать Error.

var MyError = function (message, some_other_param) 
{ 
    this.message = message; 
    this.some_other_param = some_other_param; 
} 
//I don't think you even need to do this, but it makes it nice and official 
MyError.prototype = Error; 
... 
if (something_is_wrong) 
    throw new MyError('It failed', /* here's a number I made up */ 150); 

Поймать исключения - это боль, я знаю, но опять же, так что отслеживание ссылок.

Если вы действительно нужно что-то, что приближает поведение переменных, выполненной, объекты передаются по ссылке по умолчанию, и может ловко собирать данные из других scopes--

function use_out (outvar) 
{ 
    outvar.message = 'This is my failure'; 
    return false; 
} 

var container = { message : '' }; 
var result = use_out(container); 
console.log(container.message); ///gives the string above 
console.log(result); //false 

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

Моей точкой всего этого является то, что кто-либо читает это, чтобы адаптировать свой стиль программирования к ограничениям и возможностям используемого языка, а не пытаться заставить то, чему они научились с других языков в нем.

(кстати, некоторые люди настоятельно рекомендуют против закрытия, потому что они вызывают злые побочные эффекты, но я бы не стал их слушать. Они пуристов. Побочные эффекты практически неизбежны в большом количестве приложений, не много утомительный возврат назад и преодоление препятствий. Если они вам нужны, чтобы они все вместе в аккуратном лексическом пространстве, а не разбросаны по hellscape неясных указателей, и ссылки звучат намного лучше для меня)

0

Ответы, которые я видел до сих пор, не реализуют параметры в JavaScript, поскольку они используются в C# (ключевое слово out). Это всего лишь обходной путь, который возвращает объект в случае ошибки.

Но что вы будете делать, если вам действительно нужны параметры?

Поскольку Javascript не поддерживает его напрямую, вам нужно построить что-то, что близко к параметрам выхода C#. Взгляните на этот подход, я эмулирую функцию DateTime.TryParse C# в JavaScript. Из параметров является результат, а потому, что JavaScript не предоставляет из ключевых слов, я с помощью .value внутри функции передать значение вне функции (как вдохновленный MDN suggestion):

// create a function similar to C#'s DateTime.TryParse 
 
var DateTime = []; 
 
DateTime.TryParse = function(str, result) { 
 
    result.value = new Date(str); // out value 
 
    return (result.value != "Invalid Date"); 
 
}; 
 

 
// now invoke it 
 
var result = []; 
 
if (DateTime.TryParse("05.01.2018", result)) { 
 
    alert(result.value); 
 
} else { 
 
    alert("no date"); 
 
};

Запустите фрагмент, и вы увидите, что он работает. Обратите внимание, что result необходимо инициализировать как пустой массив [], до вы вызываете функцию. Это необходимо, потому что внутри функции вы «вводите» свойство .value.


Теперь вы можете использовать шаблон выше, чтобы написать функцию в качестве одного из вашего вопроса (это также показывает, как эмулировать новый параметр отбрасывания out _ в C#):

// create a function similar to C#'s DateTime.TryParse 
 
var DateTime = []; 
 
DateTime.TryParse = function(str, result) { 
 
    result.value = new Date(str); // out value 
 
    return (result.value != "Invalid Date"); 
 
}; 
 

 
// returns false, if odb is no date, otherwise true 
 
function isLegal(odp, errorObj) { 
 
    if (DateTime.TryParse(odp, [])) { // discard result here by passing [] 
 
    // all OK: leave errorObj.value undefined and return true 
 
    return true; 
 
    } else { 
 
    errorObj.value = "ODP failed test foo"; // return error 
 
    return false; 
 
    } 
 
} 
 

 
// now test the function 
 
var odp = "xxx01.12.2018xx"; // invalid date 
 
var errorObj = []; 
 
if (!isLegal(odp, errorObj)) alert(errorObj.value); else alert("OK!");

Примечание: Вместо того, чтобы использовать параметр отбрасывания, как показано выше, в JavaScript вы могли бы ALS о использовать чек undefined, т.е. внутри проверки функции для

if (result === undefined) { 
    // do the check without passing back a value, i.e. just return true or false 
}; 

Тогда можно опустить result в качестве параметра полностью, если не требуется, чтобы вы могли ссылаться на него как

if (DateTime.TryParse(odp)) { 
    // ... same code as in the snippet above ... 
}; 
Смежные вопросы