Можно ли использовать функцию стрелки в конструкторе реагирующего компонента?
Этот вопрос похож на При использовании React Предпочтительнее использовать функции толстых стрелок или связывать функции в конструкторе?, но немного отличается. Вы можете привязать функцию к this
в конструкторе или просто применить функцию стрелки в конструкторе. Обратите внимание, что я могу использовать только синтаксис ES6 в своем проекте.
1.
class Test extends React.Component{
constructor(props) {
super(props);
this.doSomeThing = this.doSomeThing.bind(this);
}
doSomething() {}
}
2.
class Test extends React.Component{
constructor(props) {
super(props);
this.doSomeThing = () => {};
}
}
Каковы плюсы и минусы этих двух способов? Спасибо.
Ответы
Ответ 1
Вариант 1, как правило, более предпочтительно по определенным причинам.
class Test extends React.Component{
constructor(props) {
super(props);
this.doSomeThing = this.doSomeThing.bind(this);
}
doSomething() {}
}
Прототипный метод более прост в распространении. Класс Child может переопределять или расширять doSomething
с помощью
doSomething() {
super.doSomething();
...
}
Когда свойство экземпляра
this.doSomeThing = () => {};
или поле класса ES.next
doSomeThing = () => {}
вызов super.doSomething()
невозможен, потому что метод не был определен на прототипе. При переопределении это приведет к назначению свойства this.doSomeThing
дважды, в родительских и дочерних конструкторах.
Прототипные методы также доступны для методов микширования:
class Foo extends Bar {...}
Foo.prototype.doSomething = Test.prototype.doSomething;
Прототипные методы более проверяемы. Их можно шпионить, обрезать или высмеивать до создания экземпляра класса:
spyOn(Foo.prototype, 'doSomething').and.callThrough();
Это позволяет в некоторых случаях избегать условий гонки.
Ответ 2
Думаю, вы можете так хотеть. То же самое происходит с вашей первой ситуацией.
он будет работать на сцене 2 с babel. (transform-class-properties: http://babeljs.io/docs/plugins/transform-class-properties/)
(preset-stage-2: http://babeljs.io/docs/plugins/preset-stage-2/)
class Test extends React.Component{
constructor(props) {
super(props);
}
doSomeThing = () => {}
}
Ответ 3
Подход 1 более читабельен для меня и более идиоматичен.
Кроме того, объявляя методы внутри класса вместо конструктора, методы могут использоваться совместно.
class Foo {
test() {}
}
const f1 = new Foo()
const f2 = new Foo()
f1.test === f2.test // true
В подходе 2 вы будете объявлять все методы каждый раз, когда вы создаете новый экземпляр:
class Foo {
constructor() {
this.test = () => {}
}
}
const f1 = new Foo()
const f2 = new Foo()
// the method is not shareable
f1.test === f2.test // false
Теоретически подход 2 медленнее, но влияние на производительность должно быть незначительным.
Я просто пойду на подход 1, поскольку он использовался в React documentation, также я никогда не видел, чтобы кто-либо использовал подход 2.
Я просто запустил несколько образцов для проверки производительности. В последнем Chrome (Mac) объявления методов в конструкторе примерно на 90% медленнее, чем использование bind
в конструкторе.
Ответ 4
Проверьте это:
https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2&targets=&browsers=&builtIns=false&debug=false&code=class%20Dog%20%7B%0A%20%20constructor()%20%7B%0A%20%20%20%20%0A%20%20%20%20this.cat%20%3D%20_%3D%3E%20%7B%0A%20%20%20%20%20%20this%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D
Мы можем видеть переходы babel
this.doSomeThing = () => { this };
в
var _this = this;
this.doSomething = function() { _this }
edit: Я неправильно читаю ваш пост, но приведенное выше все еще верно и интересно. @CodinCat указывает на важную вещь: объявление функции внутри конструктора означает, что требуется время (хотя и очень мало), чтобы добавить эту функцию к объекту при его создании, а также, вероятно, занимает память, поскольку экземпляры этого класса не разделяют такой же метод doSomeThing.
edit2: привязка (эта) к функции фактически вызывает точные проблемы, перечисленные выше. Другими словами, два метода почти одинаковы.