Я должен избегать использования Java, Маркируют Statements?

tl; dr: Нет! Функции стрелок и декларации функций / выражения не являются эквивалентными и не могут быть заменены вслепую. Если функция, которую вы хотите заменить, not использует this, arguments и не вызывается с new, тогда да.


Как это часто бывает: это зависит. Функции Arrow имеют другое поведение, чем декларации / выражения функций, поэтому давайте сначала рассмотрим различия:

1. Функции Lexical this и arguments

не имеют собственных привязок this или arguments. Вместо этого эти идентификаторы разрешаются в лексической области, как и любая другая переменная. Это означает, что внутри функции стрелки this и arguments относятся к значениям this и arguments в окружающей среде, функция стрелки определена в (т.е. «снаружи» стрелка )

В случае выражения функции, this относится к объекту, который был создан внутри createObject. В функциональном случае стрелки this относится к this самого createObject.

Это делает функции стрелок полезными, если вам нужно получить доступ к this текущей среды:

// currently common pattern
var that = this;
getData(function(data) {
  that.data = data;
});

// better alternative with arrow functions
getData(data => {
  this.data = data;
});

Обратите внимание, что это также означает, что не можно установить функцию стрелки this с .bind или .call.

Если вы не очень знакомы с this, рассмотрим чтение

2. Функции стрелок не могут быть вызваны с помощью new

ES2015 различает функции, доступные call , и функции, которые являются конструкцией . Если функция конструируется, ее можно вызвать с помощью new, то есть new User(). Если функция является вызываемой, ее можно вызвать без new (т. Е. Вызов нормальной функции).

Функции, созданные посредством деклараций / выражений функций, являются конструктивными и вызываемыми. Функции стрелок (и методы) являются только вызываемыми. class конструкторы только конструктивны.

Если вы пытаетесь вызвать функцию, не вызываемую вызовом, или построить неконструируемую функцию, вы получите ошибку времени выполнения.


Зная это, мы можем указать следующее.

Сменный:

  • Функции, которые не используют this или arguments.
  • Функции, которые используются с .bind(this)

Не сменный:

  • Функции конструктора
  • Функция / методы, добавленные к прототипу (поскольку они обычно используют функции this)
  • Variadic (если они используют arguments (см. ниже))

Давайте рассмотрим это более подробно с помощью ваших примеров:

Функция конструктора

Это не будет работать, потому что функции стрелок нельзя вызвать с помощью new. Продолжайте использовать объявление / выражение функции или используйте class.

Способы прототипа

Скорее всего нет, потому что методы прототипа обычно используют this для доступа к экземпляру. Если они не используют this, вы можете его заменить. Однако, если вы в первую очередь заботитесь о сжатом синтаксисе, используйте class с его синтаксисом сжатого метода:

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

Методы объекта

Аналогично для методов в объектном литерале. Если метод хочет ссылаться на сам объект через this, продолжайте использовать функциональные выражения или используйте новый синтаксис метода:

const obj = {
  getName() {
    // ...
  },
};

Обратные вызовы

Это зависит. Вы должны обязательно заменить его, если вы наложили внешний this или используете .bind(this):

// old
setTimeout(function() {
  // ...
}.bind(this), 500);

// new
setTimeout(() => {
  // ...
}, 500);

Но: Если код, вызывающий обратный вызов, явно устанавливает this на определенное значение , как это часто бывает с обработчиками событий, особенно с jQuery, и обратный вызов использует this (или arguments), вы не можете использовать функцию стрелки!

Variadic функции

Поскольку функции стрелок не имеют собственных arguments, вы не можете просто заменить их функцией стрелки. Однако ES2015 вводит альтернативу использованию arguments: параметр rest .

// old
function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// new
const sum = (...args) => {
  // ...
};

Связанный вопрос:

Дополнительные ресурсы:

67
задан display_name 30 January 2014 в 07:19
поделиться

9 ответов

Много алгоритмов выражаются более легко, если можно перейти через два цикла (или цикл, содержащий оператор переключения). Не плохо себя чувствуйте об этом. С другой стороны, это может указать на чрезмерно сложное решение. Поэтому отступите и посмотрите на проблему.

Некоторые люди предпочитают "однократный въезд, единственный выход" подход ко всем циклам. То есть предотвращение повреждения (и продолжаются) и рано возвращается для циклов в целом. Это может привести к некоторому дублирующему коду.

то, Что я сильно постарался бы не делать, представляет auxilary переменные. Сокрытие потока управления в состоянии добавляет к беспорядку.

маркированные циклы Разделения в два метода могут быть трудными. Исключения, вероятно, слишком тяжелы. Попробуйте однократный въезд, единственный подход выхода.

49
ответ дан Tom Hawtin - tackline 24 November 2019 в 14:34
поделиться

Маркировки похожи на goto's: Используйте их экономно, и только когда они делают Ваш код быстрее и , что еще более важно, более понятным,

, например, Если Вы находитесь в больших циклах шесть уровней глубоко, и Вы встречаетесь с условием, которое делает остальную часть цикла бессмысленной для завершения, нет никакого смысла в наличии 6 дополнительных лазеек в операторах условия для выхода из цикла рано.

Маркировки (и goto's) не являются злыми, это просто, что иногда люди используют их плохими способами. Большую часть времени мы на самом деле пытаемся записать наш код, таким образом, это понятно для Вас и следующего программиста, который приезжает. Создание его uber-быстро является вопросом второстепенной важности (опасаться преждевременной оптимизации).

, Когда Маркировки (и goto's) неправильно используются, они делают код менее читаемым, который вызывает горе для Вас и следующего разработчика. Компилятор не заботится.

33
ответ дан BIBD 24 November 2019 в 14:34
поделиться

Существует немного случаев, когда Вам нужны маркировки, и они могут сбивать с толку, потому что они редко используются. Однако, если необходимо использовать тот, затем используют тот.

BTW: это компилирует и работает.

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}
27
ответ дан Community 24 November 2019 в 14:34
поделиться

Мне любопытно услышать, какова Ваша альтернатива маркировкам. Я думаю, что это в значительной степени собирается свести к аргументу "возврата как можно раньше" по сравнению с "использованием переменную, чтобы содержать возвращаемое значение, и только возвратиться в конце".

Маркировки являются довольно стандартными, когда у Вас есть вложенные циклы. Единственным путем они действительно уменьшаются, удобочитаемость - когда другой разработчик никогда не видел их прежде и не понимает то, что они имеют в виду.

8
ответ дан Outlaw Programmer 24 November 2019 в 14:34
поделиться

Я никогда не видел маркировки, используемые "в дикой природе" в коде Java. Если Вы действительно хотите повредиться через вложенные циклы, посмотрите, можно ли осуществить рефакторинг метод так, чтобы ранний оператор возврата сделал то, что Вы хотите.

Технически, я предполагаю, что нет большого различия между ранним возвратом и маркировкой. Практически, тем не менее, почти каждый Java-разработчик видел ранний возврат и знает то, что он делает. Я предположил бы, что многие разработчики будут, по крайней мере, удивлены маркировкой, и вероятно перепутаны.

мне преподавали однократный въезд / единственная ортодоксальность выхода в школе, но я с тех пор приехал для понимания ранних операторов возврата и убегающий из циклов как способ упростить код и сделать его более ясным.

5
ответ дан Don Kirkby 24 November 2019 в 14:34
поделиться

Я спорил бы в пользу них в некоторых местоположениях, я нашел их особенно полезными в этом примере:


nextItem: for(CartItem item : user.getCart()) {

  nextCondition : for(PurchaseCondition cond : item.getConditions()) {
     if(!cond.check())
        continue nextItem;
     else
        continue nextCondition;

  }
  purchasedItems.add(item);
}
5
ответ дан Ceilingfish 24 November 2019 в 14:34
поделиться

Я думаю с новым циклом foreach, маркировка может быть действительно ясной.

, Например:

sentence: for(Sentence sentence: paragraph) {
  for(String word: sentence) {
    // do something
    if(isDone()) {
      continue sentence;
    }
  }
}

я думаю, что взгляды действительно очищают при наличии Вашей маркировки то же как Вашу переменную в новом для - каждый. На самом деле возможно, Java должен быть злым и добавить неявные маркировки для - каждый переменные heh

5
ответ дан Pyrolistical 24 November 2019 в 14:34
поделиться

Я никогда не использую маркировки в своем коде. Я предпочитаю создавать защиту и инициализировать ее к пустой указатель или другое необычное значение. Эта защита часто является объектом результата. Я не видел ни одного из своих коллег, использующих маркировки, ни нашел любого в нашем репозитории. Это действительно зависит от Вашего стиля кодирования. По-моему, использование маркировок уменьшило бы удобочитаемость, поскольку это не общая конструкция, и обычно это не используется в Java.

3
ответ дан Bartosz Bierkowski 24 November 2019 в 14:34
поделиться

Я использовал цикл с меткой Java для реализации метода Sieve для поиска простых чисел числа (сделано для одной из математических задач Эйлера), что сделало его в 10 раз быстрее по сравнению с вложенными циклами. Например, если (определенное условие) вернуться во внешний цикл.

private static void testByFactoring() {
    primes: for (int ctr = 0; ctr < m_toFactor.length; ctr++) {
        int toTest = m_toFactor[ctr];
        for (int ctr2 = 0; ctr2 < m_divisors.length; ctr2++) {
            // max (int) Math.sqrt(m_numberToTest) + 1 iterations
            if (toTest != m_divisors[ctr2]
                        && toTest % m_divisors[ctr2] == 0) {
                continue primes; 
            }
        } // end of the divisor loop
    } // end of primes loop
} // method

Я спросил программиста на C ++, насколько плохи маркированные циклы, он сказал, что будет использовать их экономно, но иногда они могут пригодиться. Например, если у вас есть 3 вложенных цикла и при определенных условиях вы хотите вернуться к самому внешнему циклу.

Итак, у них есть свое применение, это зависит от проблемы, которую вы пытались решить.

5
ответ дан 24 November 2019 в 14:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: