1. ホーム
  2. ジャバスクリプト

[解決済み】ES2015で名前付き矢印関数を書くには?

2022-04-21 03:10:46

質問

の新しい矢印構文に変換しようとしている関数があります。 ES6 . これは名前付き関数です。

function sayHello(name) {
    console.log(name + ' says hello');
}

var文を使わずに名前をつける方法はないでしょうか。

var sayHello = (name) => {
    console.log(name + ' says hello');
}

当然ながら、この関数は定義してからでないと使えません。 以下のような感じです。

sayHello = (name) => {
        console.log(name + ' says hello');
    }

で行う新しい方法はありますか? ES6 ?

解決方法は?

<ブロッククオート

ES2015 で名前付き矢印関数を書くには?

質問で断定された方法で行うのです。変数名やプロパティ名がJavaScriptエンジンの名前として合理的に使用できるような代入やプロパティ初期化子の右側に置くのです。そこには その他 という方法がありますが、そうすることが正しく、仕様で完全にカバーされています。

仕様上、この関数には真名があります。 sayHello :

var sayHello = name => {
    console.log(name + ' says hello');
};

で定義されているのが現状です。 Assignment Operators > Runtime Semantics: 評価 ここで、抽象的な ネームドエバリュエーション の操作(現在のステップ1.c.i)。(これが適用される場所は、そこのヘッダーの NamedEvalution にマウスカーソルを合わせて "References" をクリックするとわかります)。(以前は、ES2019の前に Assignment Operators > Runtime Semantics(代入演算子)。評価 中古 抽象的なSetFunctionName操作 という仕様で、ステップ1.e.iiiがありますが、ES2019以降ではこの仕様の抽象化はNamedEvalutionに置き換えられています)。

同じように PropertyDefinitionEvaluation はNamedEvalutionを使用しているため、この関数に真の名前を与えています。

let o = {
    sayHello: name => {
        console.log(`${name} says hello`);
    }
};

最近のエンジンでは、このような記述に対して、すでに関数の内部名称が設定されています。

例えば、Chrome、Edge(Chromiumベース、v79以降)、Firefoxで、ウェブコンソールを開き、このスニペットを実行します。

"use strict";
let foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
    foo();
} catch (e) {
    console.log(e.stack);
}

Chrome 51以上、Firefox 53以上(および実験フラグを持つ"Legacy" Edge 13以上、または"Chromium" Edge 79以降)で、それを実行すると、こうなります。

foo.name is: foo
エラー
    at foo (http://stacksnippets.net/js:14:23)
    http://stacksnippets.net/js:17:3 にて

このように foo.name is: fooError...at foo .

Chrome 50以前、Firefox 52以前、およびLegacy Edgeでは、実験フラグがないため、代わりにこのように表示されます。 Function#name プロパティを使用します。

foo.nameは。
エラー
    at foo (http://stacksnippets.net/js:14:23)
    http://stacksnippets.net/js:17:3 にて

から名前が消えていることに注意してください。 foo.name is: しかし、それは がスタックトレースに表示される。ただ、実際に実装してみると name プロパティ は他の ES2015 機能よりも優先順位が低かったのですが、Chrome と Firefox には実装され、Edge にはフラグが立っています。

<ブロッククオート

明らかに、私はこの関数を定義した後にのみ使用することができます

正解です。関数 宣言 のみで、アロー関数のための構文はありません。 という構文があり、旧式の名前付き関数式では名前に相当する矢印がありません ( var f = function foo() { }; ). に相当するものがないわけです。

console.log(function fact(n) {
    if (n < 0) {
        throw new Error("Not defined for negative numbers");
    }
    return n == 0 ? 1 : n * fact(n - 1);
}(5)); // 120

2つの表現に分割する必要があります (いずれにせよ、そうするべきだと思います。) :

const fact = n => {
    if (n < 0) {
        throw new Error("Not defined for negative numbers.");
    }
    return n == 0 ? 1 : n * fact(n - 1);
};
console.log(fact(5));

もちろん、もしあなたが ある を1つの式で表現する必要がある場合は、いつでも矢印関数を使用することができます。

console.log((() => {
    const fact = n => {
        if (n < 0) {
            throw new Error("Not defined for negative numbers.");
        }
        return n == 0 ? 1 : n * fact(n - 1);
    };
    return fact(5);
})()); // 120

この方法は美しいとは言えませんが、絶対に、絶対に、単一の式ラッパーが必要な場合に有効です。


余談ですが、関数の名前を代入先の識別子から取得させたくない場合はどうすればよいでしょうか。例えば しない 欲しい example.name であること "example" ここで?

const example = () => {};
console.log(example.name); // "example"

NamedEvaluationを使用しない任意の式を使用することで回避することができます。おそらく、この種のものとして最もよく知られているのは、コンマ演算子でしょう。

const example = (0, () => {});
//              ^^^−−−−−−−−−^
console.log(example.name); // ""

0 は評価された後、捨てられるので 0 がポピュラーな選択です。カンマ演算子を介して関数を渡すと、代入と関数式の間の直接的なリンクが壊れ、NamedEvaluationが名前を提供するのを防ぎます。 example を関数に使用することができます。(これは、他の有名なコンマ演算子の使い方と同様で、例えば (0, object.example)() を呼び出す。 object.example なし 作成 object の値は this を呼び出すか、あるいは (0, eval)("code") を行う。 eval しかし、通常のように現在のスコープで実行されるわけではありません)。

(ありがとうございました セバスチャン・サイモン コメントでこの点を指摘していただきました)