#javascript
#javascript
Вопрос:
-
если
function( arg1, arg2 )
я прав, полагая, чтоarg1
это гарантированно вычисляется раньшеarg2
(в отличие, например, от классического C)? -
есть ли какой-либо способ создать функцию, в которой аргументы не вычисляются, а скорее оцениваются по требованию? например,
if( cond1 || cond2 )
вычисляетсяcond2
тогда и только тогда, когдаcond1
равно false. возможно ли написать нашу собственнуюif
подобную функцию?
например, могу ли я написать функцию, подобную oracle nvl( arg1, arg2, ... )
, которая возвращает первый ненулевой аргумент, лениво оценивая их. при обычном вызове функции все аргументы вычисляются до выполнения тела функции.
Ответ №1:
Аргументы функции вычисляются до того, как они передаются функции, поэтому то, что вы запрашиваете, технически невозможно. Однако вы могли бы сделать это:
function nvl() {
for (var i = 0; i < arguments.length; i ) {
var res = arguments[i]();
if (res)
return res;
}
}
nvl(function() { return false; },
function() { return 7; },
function() { return true; });
Вызов nvl
возвращает 7
.
Создаются все оболочки функций, но внутри вычисляются только тела первых двух nvl
.
Это не совсем красиво, но это позволило бы вам предотвратить дорогостоящую операцию в теле любой из функций после того, как первая вернет истинное значение.
Комментарии:
1. ты больной щенок, и я тебя хвалю. (хотя для вашего примера nvl() false будет возвращено, поскольку оно не равно null.) нужно ли вам также что-то изменить в области видимости, чтобы функции вызывались в одной и той же области?
2. Это совершенно бессмысленно (без обид). Код
false || 7 || true
обладает идентичной функциональностью, как я пытался указать. @cc young — нет, этого не будет.if(res)
это не нулевая проверка, это ложная проверка.3. Я знаю, что ваш код выполнил то, что вы сказали, и я думал, что выразил свою признательность — все, что я пытался сделать, это сказать, что оригинальный oracle nvl() работает не так — что совершенно не отражается на вашем коде
4. @cwolves — Если вы принимаете «идентичный» за «вроде как одинаковый», то да. Это делается в функции, которую ищет OP. Ваш пример очень хорош и релевантен, но это невозможно выполнить в функции, потому что аргументы все равно будут оценены первыми.
5. OP не знает, о чем он просит. Он запрашивает функциональность с другого языка, потому что это то, к чему он привык. Если вы хотели это в вызове функции, это просто
fn(false || 7 || true)
, но это не то, чего хотел OP, он хотел функцию типа NVL, которую вы написали, но эта функция бесполезна, потому что ее можно на 100% заменить наfalse || 7 || true
. Использование оператора OR ЯВЛЯЕТСЯ правильным способом сделать это в JavaScript; копирование способа выполнения другого языка — нет.
Ответ №2:
в вашем первом примере, да, если вы вызываете функцию, они будут оцениваться по порядку.
Во 2-м примере JS не оценивает каждый параметр (точно так же, как C), например:
if(true || x ){
x никогда не будет запускаться.
Что именно вы пытаетесь сделать?
Комментарии:
1. хороший пример … прекрасно показывает, как условия лениво вычисляются в javascript.
2. правильно! хотелось бы написать функцию, подобную oracle <code>nvl()</code>, которая возвращает первый ненулевой аргумент. как и <code>if</code>, аргументы должны оцениваться лениво.
3. в этом нет смысла.
||
Оператор выполняет то же самое:cond1 || cond2() || cond3()
и т.д. Он будет вычисляться только до тех пор, пока значение не будет равно false.
Ответ №3:
- ДА
- Да, с помощью
if(cond1 || cond2)
условие 2 будет вычислено, если условие 1 равно false.
Вот функция, которая возвращает первый истинный аргумент:
function firstDefinedArgument(){
for(var i in arguments){
if(arguments[i]){
return arguments[i];
}
}
}
Так, например, firstDefinedArgument(0, null, undefined, "", "hello", "goodbye")
возвращалось бы "hello"
.
Если бы вы хотели вернуть первый ненулевой аргумент вместо первого истинного, вы бы заменили if(arguments[i])
на if(arguments[i] !== null)
. Эта функция вернет 0
результат в приведенном выше примере.
Комментарии:
1. правильно, но хотелось бы написать функцию, которая ведет себя аналогично
2. @cc young Я создал подобную функцию. Это то, что вы хотели?
3. Нет. Аргументы все еще оцениваются до их передачи. То, чего хочет OP, в принципе, невозможно, хотя у меня есть идея.