Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Получить имя функции внутри функции не используя callee (https://javascript.ru/forum/misc/79421-poluchit-imya-funkcii-vnutri-funkcii-ne-ispolzuya-callee.html)

drwhite 05.02.2020 20:51

Получить имя функции внутри функции не используя callee
 
Приветствую, камрады, можно ли сделать как в PHP:
public function func($in_params)
{ 
    $__F__ = __FUNCTION__;
    ...
    if (...) $__F__($in_params);
}

чтобы не зависеть от имени функции, но не используя callee?

Vlasenko Fedor 05.02.2020 22:02

Пример варианта для window
<script>
function test(name) {
    if (typeof window[name] === "function") {
        window[name]();
    } else {
        alert("Function not declared")
    }
}

function one() {
    alert('One');
}

test("one");
test("two");

</script>

Malleys 06.02.2020 03:40

Poznakomlus, пишут ведь, что «чтобы не зависеть от имени функции». Ещё ваш вариант предполагает засорение глобального объекта, а также его изменение! Также у вас не соблюдена чистота функции. Также вы не показали, как получить функцию внутри функции не используя callee!

drwhite, в JavaScript как раз для этого и есть arguments.callee, который указывает на функцию.

Однако стоит учитывать, что по имени функции не всегда возможно обратиться к самой функции, поэтому лучше говорить о ссылке на функцию.
function factorial(n) {
    if(n % 1 !== 0 || n < 0) throw Error("n ∈ Z ⋀ n ≥ 0");
    if(n === 0) return 1;
    return n * arguments.callee(n - 1);
}

alert(factorial(5)); // 5! = 120


Однако, если вы вдруг решили, что вам по каким-то причинам arguments.callee не подходит (по каким?), то вы можете использовать Y-комбинатор!

var Y =
  f => (
      g => x => f(g(g))(x)
    )(
      g => x => f(g(g))(x)
    );

var factorial = Y(fn => n => {
    if(n % 1 !== 0 || n < 0) throw Error("n ∈ Z ⋀ n ≥ 0");
    if(n === 0) return 1;
    return n * fn(n - 1);
});

alert(factorial(5)); // 5! = 120
Обращение функции к самой себе вообще не предполагает наличие глобальной ссылки. Т. е. поскольку она не называет себя по имени, она не связана тесно с самой собой.

рони 06.02.2020 08:39

:write: может я что-то не понимаю, но альтернативы arguments.callee в решениях выше Poznakomlus и
Malleys
не увидел.

Aetae 06.02.2020 10:29

Потому что её нет.
Если вы работаете в нестрогом режиме - у вас уже есть arguments.callee, никакого смысла в чём-то ещё нет.
Если вы работаете в строгом режиме - arguments.callee у вас отобрали специально, чтобы заметно ускорить и облегчить исполнение избавившись от сложных взаимосвязей и побочек. Альтернативы, соответственно, тут принципиально не будет.

drwhite 06.02.2020 10:48

Цитата:

Сообщение от Malleys
Однако, если вы вдруг решили, что вам по каким-то причинам arguments.callee не подходит (по каким?)

Именно потому, что оно устаревшее и вообще я за стрикт моде.

Цитата:

Сообщение от Malleys
можете использовать Y-комбинатор!

«— Будете у нас на Колыме…
— нет, уж лучше вы к нам» =)

Цитата:

Сообщение от Aetae
в строгом режиме - arguments.callee у вас отобрали специально, чтобы заметно ускорить и облегчить исполнение избавившись от сложных взаимосвязей и побочек

Но ведь так удобно не зависеть от имени функции при рекурсии. Чем, кстати, оно может нагадить?

Malleys 06.02.2020 11:10

Цитата:

Сообщение от рони
альтернативы arguments.callee в решениях выше Poznakomlus и
Malleys не увидел.

В моём втором примере показазан Y-комбинатор.

Цитата:

Сообщение от Aetae
Альтернативы, соответственно, тут принципиально не будет.

Цитата:

Сообщение от drwhite
Но ведь так удобно не зависеть от имени функции при рекурсии.

Y-комбинатор делает именно то, что вы хотите. Или что вы имеете в виду, когда пишете «не зависеть от имени функции при рекурсии»?

рони 06.02.2020 11:18

Цитата:

Сообщение от Malleys
Y-комбинатор делает именно то, что вы хотите. Или что вы имеете в виду, когда пишете «не зависеть от имени функции при рекурсии»?

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

drwhite 06.02.2020 12:08

Цитата:

Сообщение от Malleys
Y-комбинатор делает именно то, что вы хотите. Или что вы имеете в виду, когда пишете «не зависеть от имени функции при рекурсии»?

хочу как-то так:
function func($params)
{
    ...
    if (...) self($params);
}


чтобы имя функции указывалось один раз, без лишних переменных, без NFE и в strict mode =)

Vlasenko Fedor 06.02.2020 12:38

<script>
function test() {
    try {
        throw  new Error( "Get name")
    } catch (e) {
        console.log(e.stack);
    }
}
test();
</script>

название функции есть в стеке вызовов, однако этот стек по разному работает в броузерах
если я вас правильно понял


Часовой пояс GMT +3, время: 18:32.