Czy "funkcje strzałek" i "funkcje" są równoważne / wymienne?
Funkcje strzałek w ES2015 zapewniają bardziej zwięzłą składnię.
- Czy mogę teraz zastąpić wszystkie deklaracje / wyrażenia funkcji funkcjami strzałek?
- na co mam uważać?
Przykłady:
Funkcja konstruktora
function User(name) {
this.name = name;
}
// vs
const User = name => {
this.name = name;
};
Metody prototypowe
User.prototype.getName = function() {
return this.name;
};
// vs
User.prototype.getName = () => this.name;
Metody obiektowe (dosłowne)
const obj = {
getName: function() {
// ...
}
};
// vs
const obj = {
getName: () => {
// ...
}
};
Callbacks
setTimeout(function() {
// ...
}, 500);
// vs
setTimeout(() => {
// ...
}, 500);
Funkcje Zmienne
function sum() {
let args = [].slice.call(arguments);
// ...
}
// vs
const sum = (...args) => {
// ...
};
3 answers
Tl; dr: Nie! funkcje strzałek i deklaracje / wyrażenia funkcji nie są równoważne i nie można ich zastąpić na ślepo.
Jeśli funkcja, którą chcesz zastąpić, Nie , użyj this
, arguments
i nie jest wywoływana przez new
, to tak.
Jak często: To zależy . Funkcje strzałek mają inne zachowanie niż deklaracje / wyrażenia funkcji, więc spójrzmy najpierw na różnice: {]}
1. Leksykalne this
i arguments
Funkcje strzałek nie mają własnych wiązań this
lub arguments
. Zamiast tego identyfikatory te są rozwiązywane w zakresie leksykalnym, jak każda inna zmienna. Oznacza to, że wewnątrz funkcji strzałki, this
i arguments
odnoszą się do wartości this
i arguments
w środowisku funkcja strzałki jest zdefiniowana W (tzn. "na zewnątrz" funkcji strzałki):
// Example using a function expression
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: function() {
console.log('Inside `bar`:', this.foo);
},
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
// Example using a arrow function
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: () => console.log('Inside `bar`:', this.foo),
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
W przypadku wyrażenia funkcji, this
odnosi się do obiektu który powstał wewnątrz createObject
. W przypadku funkcji strzałki, this
odnosi się do this
z createObject
.
To sprawia, że funkcje strzałek są przydatne, jeśli potrzebujesz dostępu do this
bieżącego środowiska:
// currently common pattern
var that = this;
getData(function(data) {
that.data = data;
});
// better alternative with arrow functions
getData(data => {
this.data = data;
});
Zauważ, że oznacza to również, że nie można ustawić funkcji strzałki this
za pomocą .bind
lub .call
.
Jeśli nie jesteś zaznajomiony z this
, rozważ przeczytanie
2. Funkcji strzałek nie można wywoływać za pomocą new
ES2015 rozróżnia funkcje, które są call able i funkcje, które są construct able. Jeśli funkcja jest konstruktywna, można ją wywołać za pomocą new
, tzn. new User()
. Jeśli funkcja jest wywoływalna, może być wywołana bez new
(tj. normalnego wywołania funkcji).
Funkcje tworzone przez deklaracje / wyrażenia funkcji są zarówno konstruktywne, jak i możliwe do wywołania.
Funkcje strzałek (i metody) można wywoływać tylko.
class
konstruktory są tylko konstruktywne.
Jeśli próbujesz wywołać funkcję, której nie można wywołać lub skonstruować funkcję, której nie można zbudować, pojawi się błąd runtime.
Wiedząc o tym, możemy stwierdzić, co następuje.
- funkcje, które nie używają
this
lubarguments
. - funkcje, które są używane z
.bind(this)
Nie "Type": "content"]}
- funkcje konstruktora
- funkcja / metody dodane do prototypu (ponieważ zwykle używają
this
) - Funkcje Zmienne (jeśli używają
arguments
(patrz niżej))
Przyjrzyjmy się temu bliżej, używając Twoich przykładów:
Funkcja konstruktora
To nie zadziała, ponieważ funkcje strzałek nie mogą być wywoływane przez new
. Używaj deklaracji / wyrażenia funkcji lub użycia class
.
Prototype metody
Najprawdopodobniej nie, ponieważ metody prototypowe zwykle używają this
, aby uzyskać dostęp do instancji. Jeśli nie użyją this
, możesz go zastąpić. Jeśli jednak zależy Ci przede wszystkim na zwięzłej składni, użyj class
ze składnią zwięzłej metody:
class User {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
Metody obiektowe
Podobnie dla metod w dosłownym obiekcie. Jeśli metoda chce odwoływać się do samego obiektu za pomocą this
, należy używać wyrażeń funkcji lub użyć nowej metody składnia:
const obj = {
getName() {
// ...
},
};
Callbacks
To zależy. Zdecydowanie powinieneś go zastąpić, jeśli aliasujesz zewnętrznąthis
lub używasz .bind(this)
:
// old
setTimeout(function() {
// ...
}.bind(this), 500);
// new
setTimeout(() => {
// ...
}, 500);
Ale: jeśli kod wywołujący wywołanie zwrotne jawnie ustawia this
na określoną wartość, jak to często bywa w programach obsługi zdarzeń, zwłaszcza w jQuery, a wywołanie zwrotne używa this
(lub arguments
), nie można użyć funkcji strzałki!
Funkcje Zmienne
Od arrow funkcje nie mają własnych arguments
, nie można ich po prostu zastąpić funkcją strzałki. Jednak ES2015 wprowadza alternatywę dla użycia arguments
: parametr rest .
// old
function sum() {
let args = [].slice.call(arguments);
// ...
}
// new
const sum = (...args) => {
// ...
};
Podobne pytanie:
- kiedy należy używać funkcji strzałek w ECMAScript 6?
- czy funkcje strzałek ES6 mają swoje własne argumenty, czy nie?
- jakie są różnice (jeśli występują) między funkcjami strzałek ES6 a funkcjami związanymi z Funkcja.prototyp.bind?
- jak używać funkcji strzałek (publicznych pól klas) jako metod klasowych?
Dalsze zasoby:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-20 06:23:08
Arrow functions = > najlepsza jak dotąd funkcja ES6. Są ogromnie potężny dodatek do ES6, którego używam stale.
Czekaj, nie możesz używać funkcji strzałek wszędzie w kodzie, jej nie będzie działać we wszystkich przypadkach, takich jak this
gdzie funkcje strzałek nie są użyteczne. Bez wątpienia funkcja arrow jest świetnym dodatkiem, który przynosi prostotę kodu.
Ale nie można użyć funkcji strzałki, gdy wymagany jest dynamiczny kontekst: definiowanie metod, tworzenie obiektów z konstruktorów, uzyskać cel z tego podczas obsługi zdarzeń.
Funkcje strzałek nie powinny być używane, ponieważ:
-
Nie mają
this
Używa "zakresu leksykalnego", aby dowiedzieć się, jaka jest wartość "
this
" powinno być. W prostym słowniku leksykalnym używa się "this
" z wewnątrz ciała funkcji. -
Nie mają
arguments
Funkcje strzałek nie mają obiektu
arguments
. Ale to samo funkcjonalność można osiągnąć za pomocą parametrów spoczynkowych.let sum = (...args) => args.reduce((x, y) => x + y, 0)
sum(3, 3, 1) // output - 7
` -
Nie mogą być używane z
new
Funkcje strzałek nie mogą być konstruowane, ponieważ nie mają właściwości prototypu.
Kiedy używać funkcji strzałek, a kiedy nie:
- nie używaj do dodawania funkcji jako właściwości obiektu, ponieważ nie mogę się do tego dostać.
- wyrażenia funkcyjne są najlepsze dla metod obiektowych. Funkcje strzałek
są najlepsze dla wywołań zwrotnych lub metod takich jak
map
,reduce
, lubforEach
. - użyj deklaracji funkcji dla funkcji, które wywołujesz po nazwie (ponieważ są wciągane).
- użyj funkcji strzałek dla wywołań zwrotnych (ponieważ mają tendencję do terser).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Aby użyć funkcji strzałek z function.prototype.call
, wykonałem funkcję pomocniczą na prototypie obiektu:
// Using
// @func = function() {use this here} or This => {use This here}
using(func) {
return func.call(this, this);
}
Użycie
var obj = {f:3, a:2}
.using(This => This.f + This.a) // 5
Edit
Nie potrzebujesz pomocnika. Można zrobić:var obj = {f:3, a:2}
(This => This.f + This.a).call(undefined, obj); // 5
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-16 02:23:29