Richtige Verwendung von const zum Definieren von Funktionen in JavaScript

181

Ich bin interessiert, ob es Grenzen gibt, welche Arten von Werten constin JavaScript festgelegt werden können - insbesondere Funktionen. Ist das gültig? Zugegeben, es funktioniert, aber wird es aus irgendeinem Grund als schlechte Praxis angesehen?

const doSomething = () => {
   ...
}

Sollten alle Funktionen in ES6 so definiert werden? Es scheint nicht so, als hätte sich das durchgesetzt, wenn ja.

Vielen Dank für alle Kommentare!

David Sinclair
quelle
Sie scheinen mehrere Fragen zu stellen: 1) "Ich bin interessiert, ob es Grenzen gibt, welche Arten von Werten mit const in JavaScript festgelegt werden können." Nr. 2) "Ist dies gültig?" Ja. 3) " Wird es aus irgendeinem Grund als schlechte Übung angesehen?" Ich denke, es gab es nicht lange genug, um etwas darüber zu sagen, aber ich verstehe nicht, warum dies Pad-Übung sein sollte. Es ist nicht viel anders als var doSomething = <function def>;. 4) "Sollten alle Funktionen in ES6 so definiert werden?" Scheint mir umständlich. Ich mag Funktionsdeklarationen. Jeder für sich.
Felix Kling
1
So wie ich es sehe (Meinung, keine Tatsache), ist es sinnvoll, wenn Sie die Neudefinition von Funktionen nicht zulassen möchten. Ob es vernünftig ist oder ob es eine funktionale Verwendung hat - das ist umstritten. Wenn Sie der Meinung sind, dass es zu Ihrem Anwendungsszenario passt, kann meiner Meinung nach niemand Ihre Entscheidung argumentieren und es für eine schlechte Praxis halten.
Mjh
4
Ich denke, die Frage ist, womit Sie etwas erreichen wollen const. Möchten Sie verhindern, dass Sie die Funktion überschreiben? Ich würde annehmen, dass Sie Ihren Code kennen, um dies sowieso nicht zu tun. Möchten Sie die Absicht ausdrücken doSomething, dh dass es eine Funktion enthält und seinen Wert nicht ändert? Ich denke, Funktionserklärungen kommunizieren diese Absicht auch klar. Wenn Sie also einen "Laufzeitschutz" vor dem Überschreiben benötigen, entscheiden Sie sich dafür. Ansonsten sehe ich nicht viel Nutzen. Wenn Sie in erster Linie verwenden var foo = function() {};würden, würde ich natürlich constanstelle von verwenden var.
Felix Kling
5
@FelixKling, "Ich würde annehmen, dass Sie Ihren Code kennen, um dies sowieso nicht zu tun." - Das ist ein ziemlich schlechtes Argument. Ansonsten macht es überhaupt keinen Sinn const.
Meandre

Antworten:

249

Es gibt kein Problem mit dem, was Sie getan haben, aber Sie müssen sich an den Unterschied zwischen Funktionsdeklarationen und Funktionsausdrücken erinnern.

Eine Funktionsdeklaration, das heißt:

function doSomething () {}

Wird ganz nach oben gehoben (und wie letund wieconst Zielfernrohrs gehoben sie sind ebenfalls blockumfangend).

Dies bedeutet, dass Folgendes funktioniert:

doSomething() // works!
function doSomething() {}

Ein Funktionsausdruck, das heißt:

[const | let | var] = function () {} (or () =>

Ist die Erstellung einer anonymen Funktion (function () {} ) und die Erstellung einer Variablen und dann die Zuordnung dieser anonymen Funktion zu dieser Variablen.

Die üblichen Regeln für das Heben von Variablen innerhalb eines Bereichs - Variablen mit Blockbereich (let und const) also nicht undefinedan die Spitze ihres Blockbereichs.

Das heisst:

if (true) {
    doSomething() // will fail
    const doSomething = function () {}
}

Wird seitdem scheitern doSomething nicht definiert ist. (Es wird ein werfen ReferenceError)

Wenn Sie zur Verwendung wechseln, wird vardie Variable angehoben, aber sie wird auf initialisiertundefined dass der obige Codeblock immer noch nicht funktioniert. (Dadurch wird ein TypeErrorDa doSomethingausgelöst, das zum Zeitpunkt des Aufrufs keine Funktion ist.)

In Bezug auf Standardpraktiken sollten Sie immer das richtige Werkzeug für den Job verwenden.

Axel Rauschmayer hat einen großartigen Beitrag zu Umfang und Heben einschließlich der es6-Semantik: Variablen und Umfang in ES6

tkone
quelle
7
Ich möchte nur hinzufügen, dass es6-Klassen intern const verwenden, um den Klassennamen vor einer Neuzuweisung innerhalb der Klasse zu schützen.
user2342460
1
Ein subtiler Unterschied zwischen a function a(){console.log(this);} und b const a=_=>{console.log(this);} ist, wenn Sie es so nennen a.call(someVar);, in a wird es gedruckt someVar, in b wird es gedruckt window.
Qian Chen
99

Das Verwenden constzum Definieren von Funktionen scheint zwar ein Hack zu sein, bringt aber einige große Vorteile mit sich, die es überlegen machen (meiner Meinung nach)

  1. Dadurch wird die Funktion unveränderlich, sodass Sie sich keine Sorgen machen müssen, dass diese Funktion durch einen anderen Code geändert wird.

  2. Sie können die Syntax für fette Pfeile verwenden, die kürzer und sauberer ist.

  3. Durch die Verwendung der Pfeilfunktionen wird die thisBindung für Sie erledigt.

Beispiel mit function

// define a function
function add(x, y) { return x + y; }

// use it
console.log(add(1, 2)); // 3

// oops, someone mutated your function
add = function (x, y) { return x - y; };

// now this is not what you expected
console.log(add(1, 2)); // -1

gleiches Beispiel mit const

// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;

// use it
console.log(add(1, 2)); // 3

// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged

Gafi
quelle
1
Und Sie können die Funktion add zweimal deklarieren (x, y), aber Sie können nicht zweimal const add deklarieren = ...
TatianaP
33
1. Unveränderlichkeit ist ein echter Vorteil, aber es kommt sehr selten vor, dass jemand eine Funktion tatsächlich überschreibt. 2. Die Fettpfeilsyntax ist nicht kürzer, es sei denn, Ihre Funktion kann ein Ausdruck sein. function f(x, y) {ist 18 Zeichen, const f = (x, y) => {ist 21 Zeichen, also 3 Zeichen länger. 3. Die Beibehaltung dieser Bindung ist nur wichtig, wenn die Funktionen innerhalb einer Methode (oder einer anderen Funktion, die dies bedeutet) definiert sind. Auf der obersten Ebene ist es sinnlos. Ich sage nicht, dass Sie falsch liegen, nur dass die Gründe, die Sie erwähnen, nicht besonders relevant sind.
Nakedible
@Nakedible also was sind andere gültige Gründe?
Anish Ramaswamy
13
Ein Vorteil der altmodischen Funktionssyntax besteht darin, dass sie beim Debuggen einen Namen hat.
user949300
3
Ich würde Linters verwenden, um ein erneutes Binden der Funktionsdeklaration zu verhindern.
Franklin Yu
31

Es ist drei Jahre her, seit diese Frage gestellt wurde, aber ich stoße gerade darauf. Da diese Antwort so weit unten im Stapel liegt, erlaube mir bitte, sie zu wiederholen:

F: Ich bin interessiert, ob es Grenzen gibt, welche Arten von Werten mit const in JavaScript festgelegt werden können - insbesondere Funktionen. Ist das gültig? Zugegeben, es funktioniert, aber wird es aus irgendeinem Grund als schlechte Praxis angesehen?

Ich war motiviert, Nachforschungen anzustellen, nachdem ich einen produktiven JavaScript-Codierer beobachtet hatte, der immerconst Aussagen verwendet functions, auch wenn es keinen offensichtlichen Grund / Nutzen gibt.

Als Antwort auf " Wird es aus irgendeinem Grund als schlechte Praxis angesehen? " Lassen Sie mich sagen, IMO, ja, oder zumindest hat die Verwendung von Aussagen Vorteilefunction .

Es scheint mir, dass dies weitgehend eine Frage der Präferenz und des Stils ist. Oben sind einige gute Argumente aufgeführt, aber keines ist so klar wie in diesem Artikel:

Ständige Verwirrung: Warum ich immer noch JavaScript-Funktionsanweisungen von medium.freecodecamp.org/Bill Sourour, JavaScript-Guru, Berater und Lehrer verwende.

Ich fordere alle auf, diesen Artikel zu lesen, auch wenn Sie bereits eine Entscheidung getroffen haben.

Hier sind die wichtigsten Punkte:

Funktionsanweisungen haben zwei klare Vorteile gegenüber [const] -Funktionsausdrücken:

Vorteil Nr. 1: Klarheit der Absicht

Wenn Sie täglich Tausende von Codezeilen durchsuchen, ist es hilfreich, die Absicht des Programmierers so schnell und einfach wie möglich herauszufinden.

Vorteil Nr. 2: Reihenfolge der Erklärung == Reihenfolge der Ausführung

Im Idealfall möchte ich meinen Code mehr oder weniger in der Reihenfolge deklarieren, in der ich davon ausgehe, dass er ausgeführt wird.

Dies ist der Showstopper für mich: Auf jeden Wert, der mit dem Schlüsselwort const deklariert wurde, kann nicht zugegriffen werden, bis die Ausführung ihn erreicht.

Was ich oben beschrieben habe, zwingt uns, Code zu schreiben, der verkehrt herum aussieht. Wir müssen mit der Funktion der untersten Ebene beginnen und uns nach oben arbeiten.

Mein Gehirn funktioniert nicht so. Ich möchte den Kontext vor den Details.

Der meiste Code wird von Menschen geschrieben. Daher ist es sinnvoll, dass die Reihenfolge des Verstehens der meisten Menschen in etwa der Ausführungsreihenfolge der meisten Codes entspricht.

JMichaelTX
quelle
1
Können Sie etwas mehr zur Klarheit der Absicht sagen? Ich bekomme # 2, aber soweit ich das beurteilen kann, ist # 1 nur eine (vor?) Wiederholung von # 2. Ich kann mir einen Fall defaultErrorHandlervorstellen , dh Funktionen, denen eine eigene Konstante als anonyme Funktion zugewiesen wurde, die ich dann von Versprechen-Handlern aufrufen kann. Dies würde es mir ermöglichen, diesen Standardfehlerbehandler optional innerhalb der Funktionen nach Bedarf zu überschreiben. Einige müssen nur ein Fehlerobjekt zurückgeben, andere müssen eine http-Antwort mit unterschiedlichem Ausführlichkeitsgrad zurückgeben. Die Codestruktur kann jedoch unabhängig davon ein bekanntes Muster sein.
Jake T.
Vielleicht ist meine Idee aber zu verworren! Ich habe mich nur mit einigen neuen Praktiken beschäftigt und noch nicht viel Zeit damit verbracht, sie umzusetzen. Ich finde nur, dass ich .then( res.success, res.error )viel mehr mag als die anonymen Funktionen, die ich nur aufrufen wollte res.success(value);. Ein .then( ..., defaultErrorHandler)gemeinsames Muster könnte mit einer auf oberster Ebene definierten defaultErrorHandler-Funktion und optional einer const defaultErrorHandler = error => { ... }deklarierten Funktion innerhalb eines Funktionsbereichs hilfreich sein .
Jake T.
1
@ JakeT. RE "Können Sie etwas mehr zur Klarheit der Absicht sagen?". Nun, zuallererst wurde diese Aussage nicht von mir gemacht, sondern von freecodecamp.org/Bill Sourour, dem Autor dieses Artikels. Aber es macht für mich wirklich gesunden Menschenverstand. Wenn ich "Funktion morgen ()" lese, weiß ich sofort, dass es sich um eine Funktion handelt. Aber wenn ich "const morgen = () =>" lese, muss ich einen Moment innehalten und die Syntax in meinem Kopf analysieren, um schließlich festzustellen, OK, ja, es ist eine Funktion.
JMichaelTX
1
Eine andere Sache, wenn ich ein langes Skript von jemand anderem geschrieben habe und alle Funktionen sehen möchte, kann ich eine schnelle Suche nach "Funktion" durchführen, um sie zu finden. Oder noch besser, ich kann eine schnelle JS RegEx schreiben, um alle Funktionen zu extrahieren. IMO, die "const" -Anweisung gilt nur für Daten (keine Funktionen), die sich NICHT ändern.
JMichaelTX
10

Die Verwendung von hat einige sehr wichtige Vorteile, constund einige würden sagen, dass sie nach Möglichkeit verwendet werden sollte, da sie absichtlich und indikativ ist.

Soweit ich das beurteilen kann, ist es die indikativste und vorhersehbarste Deklaration von Variablen in JavaScript und eine der nützlichsten, weil sie so eingeschränkt ist. Warum? Weil es einige Möglichkeiten varund letErklärungen beseitigt .

Woraus können Sie schließen, wenn Sie a lesen const? Sie kennen alle folgenden Punkte, indem Sie die constDeklarationsanweisung lesen UND ohne nach anderen Verweisen auf diese Variable zu suchen:

  • Der Wert ist an diese Variable gebunden (obwohl das zugrunde liegende Objekt nicht tief unveränderlich ist).
  • Es kann nicht außerhalb des unmittelbar enthaltenden Blocks darauf zugegriffen werden
  • Aufgrund der TDZ-Regeln (Temporal Dead Zone) wird vor der Deklaration nie auf die Bindung zugegriffen.

Das folgende Zitat stammt aus einem Artikel , in dem die Vorteile von letund erläutert werden const. Außerdem wird Ihre Frage zu den Einschränkungen / Grenzen des Keywords direkter beantwortet:

Einschränkungen wie die von letund constsind eine leistungsstarke Methode, um das Verständnis von Code zu erleichtern. Versuchen Sie, so viele dieser Einschränkungen wie möglich in dem von Ihnen geschriebenen Code zu berücksichtigen. Je mehr deklarative Einschränkungen die Bedeutung eines Codes einschränken, desto einfacher und schneller ist es für Menschen, einen Code in Zukunft zu lesen, zu analysieren und zu verstehen.

Zugegeben, eine constDeklaration enthält mehr Regeln als eine varDeklaration: Block-Scoped, TDZ, Zuweisung bei Deklaration, keine Neuzuweisung. Während varAnweisungen nur Funktionsumfang signalisieren. Das Zählen von Regeln bietet jedoch nicht viel Einsicht. Es ist besser, diese Regeln in Bezug auf die Komplexität abzuwägen: Addiert oder subtrahiert die Regel die Komplexität? Im Fall von constBlock-Scoping bedeutet dies einen engeren Bereich als Funktions-Scoping. TDZ bedeutet, dass wir den Bereich von der Deklaration nicht rückwärts scannen müssen, um die Verwendung vor der Deklaration zu erkennen, und Zuweisungsregeln bedeuten, dass die Bindung immer den Bereich beibehält gleiche Referenz.

Je eingeschränkter die Anweisungen sind, desto einfacher wird ein Code. Wenn wir der Bedeutung einer Anweisung Einschränkungen hinzufügen, wird der Code weniger unvorhersehbar. Dies ist einer der Hauptgründe, warum statisch typisierte Programme im Allgemeinen leichter zu lesen sind als dynamisch typisierte. Die statische Eingabe stellt eine große Einschränkung für den Programmschreiber dar, stellt jedoch auch eine große Einschränkung für die Interpretation des Programms dar, wodurch der Code leichter verständlich wird.

In Anbetracht dieser Argumente wird empfohlen, diese nach constMöglichkeit zu verwenden, da diese Aussage uns die geringsten Denkmöglichkeiten bietet.

Quelle: https://ponyfoo.com/articles/var-let-const

mrmaclean89
quelle