Почему this.setModel не является функцией? [Дубликат]

Какова его цель, почему она была добавлена?

Назначение видно, когда в качестве параметра функции используется двоичный размер переменной длины. Функция

int foo(int n, int m, int a[n][m])  {...}   

может быть прототипирована как любая из следующих

int foo(int , int, int [][*]);
int foo(int , int, int a[*][*]);
int foo(int , int, int (*a)[*]);
int foo(int n, int, int a[n][*]);
int foo(int , int m, int a[*][m]);
int foo(int , int m, int (*a)[m]);
int foo(int n, int m, int a[n][m]); 

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

В чем разница с int[]? В чем разница с int *?

В случае 1D-массива для определения функции

int bar(int n, int a[n]} {...}  

допустим любой из следующих прототипов

int bar (int , int *);
int bar (int , int [*]);
Int bar (int , int []);
int bar (int n, int a[]);
int bar (int n, int a[n]);
int bar (int n, int [n]);   

В этом case * и n не требуется, поскольку компилятор будет рассматривать как int [*], так и int [n] как int *. Итак, с одномерным массивом вы не видите большой разницы.


ПРИМЕЧАНИЕ. При использовании массива переменной длины в качестве параметра функции важно указать параметр. Порядок параметров для первых четырех прототипов bar можно переключить, но в последних двух первых параметрах не должно быть самого массива.

int bar (int a[n], int n);  //Wrong. Compiler has not yet seen 'n'.
246
задан Felix Kling 30 March 2016 в 20:05
поделиться

2 ответа

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) => {
  // ...
};

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

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

364
ответ дан Community 18 August 2018 в 20:30
поделиться
  • 1
    Возможно, стоит упомянуть, что лексический this также влияет на super и что у них нет .prototype. – loganfsmyth 18 December 2015 в 23:13
  • 2
    Также было бы неплохо упомянуть, что они не являются синтаксически взаимозаменяемыми - функция стрелок (AssignmentExpression) не может быть просто опущена во всем, что может быть функциональным выражением (PrimaryExpression), и она довольно часто отключает людей (особенно поскольку в основных реализациях JS были ошибки синтаксического анализа). – JMM 1 April 2016 в 22:49
  • 3
    @JMM: & quot; он довольно часто отключает людей & quot; , вы можете предоставить конкретный пример? Скрываясь по спецификации, кажется, что места, где вы можете поместить FE, но не AF, в любом случае будут приводить к ошибкам во время выполнения ... – Felix Kling 1 April 2016 в 22:54
  • 4
    Конечно, я имею в виду такие вещи, как попытка немедленно вызвать функцию стрелки, такую ​​как выражение функции (() => {}()) или сделать что-то вроде x || () => {}. Вот что я имею в виду: ошибки времени выполнения (parse). (И хотя это так, довольно часто люди думают, что ошибка ошибочна.) Вы просто пытаетесь охватить логические ошибки, которые останутся незамеченными, потому что они не обязательно являются ошибками при анализе или исполнении? new 'in one - это ошибка времени выполнения? – JMM 1 April 2016 в 23:27
  • 5
    Вот некоторые ссылки на него: substack / node-browsify # 1499 , babel / babel-eslint # 245 (это стрелка асинхронного просмотра, но я подумайте, что это та же самая основная проблема), и куча вопросов на Babel, которые трудно найти сейчас, но вот один T2847 . – JMM 1 April 2016 в 23:27

Посмотрите на этот пример Plnkr

Переменная this сильно отличается timesCalled с каждым нажатием кнопки увеличивается только на 1. Ответ на мой личный вопрос:

.click( () => { } )

и

.click(function() { })

создают одинаковое количество функции при использовании в цикле, как вы можете видеть из подсчета Guid в Plnkr.

2
ответ дан jmb.mage 18 August 2018 в 20:30
поделиться
Другие вопросы по тегам:

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