tl; dr: Нет! Функции стрелок и декларации функций / выражения не являются эквивалентными и не могут быть заменены вслепую. Если функция, которую вы хотите заменить, not использует this
, arguments
и не вызывается с new
, тогда да.
Как это часто бывает: это зависит. Функции Arrow имеют другое поведение, чем декларации / выражения функций, поэтому давайте сначала рассмотрим различия:
1. Функции Lexical this
и arguments
не имеют собственных привязок this
или arguments
. Вместо этого эти идентификаторы разрешаются в лексической области, как и любая другая переменная. Это означает, что внутри функции стрелки this
и arguments
относятся к значениям this
и arguments
в окружающей среде, функция стрелки определена в (т.е. «снаружи» стрелка ) // 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
В случае выражения функции, 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
) 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) => {
// ...
};
Связанный вопрос:
Дополнительные ресурсы:
Это отредактированная версия моего исходного ответа.
bool GetProductAndVersion(CStringA & strProductName, CStringA & strProductVersion)
{
// get the filename of the executable containing the version resource
TCHAR szFilename[MAX_PATH + 1] = {0};
if (GetModuleFileName(NULL, szFilename, MAX_PATH) == 0)
{
TRACE("GetModuleFileName failed with error %d\n", GetLastError());
return false;
}
// allocate a block of memory for the version info
DWORD dummy;
DWORD dwSize = GetFileVersionInfoSize(szFilename, &dummy);
if (dwSize == 0)
{
TRACE("GetFileVersionInfoSize failed with error %d\n", GetLastError());
return false;
}
std::vector<BYTE> data(dwSize);
// load the version info
if (!GetFileVersionInfo(szFilename, NULL, dwSize, &data[0]))
{
TRACE("GetFileVersionInfo failed with error %d\n", GetLastError());
return false;
}
// get the name and version strings
LPVOID pvProductName = NULL;
unsigned int iProductNameLen = 0;
LPVOID pvProductVersion = NULL;
unsigned int iProductVersionLen = 0;
// replace "040904e4" with the language ID of your resources
if (!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductName"), &pvProductName, &iProductNameLen) ||
!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen))
{
TRACE("Can't obtain ProductName and ProductVersion from resources\n");
return false;
}
strProductName.SetString((LPCSTR)pvProductName, iProductNameLen);
strProductVersion.SetString((LPCSTR)pvProductVersion, iProductVersionLen);
return true;
}
Что-то вроде этого предоставит Вам необработанный доступ к данным ресурсов и запускать Вас:
HRSRC res = ::FindResource(NULL, MAKEINTRESOURCE(MY_VERSION_ID), RT_VERSION);
DWORD size = ::SizeofResource(NULL, res);
HGLOBAL mem = ::LoadResource(NULL, res);
LPVOID raw_data = ::LockResource(mem);
...
::FreeResource(mem);
/home/myhome/anaconda3/envs/py27/lib
– Yan King Yin
23 April 2018 в 14:45
Хорошо, немного больше googleing нашло после на CodeGuru. В основном этот подход использует объект CFileVersionInfo войти в любой данный файл. Должно быть интересно видеть, продолжает ли это работать в настоящее время рабочий.EXE файл и на Windows CE.
/usr/local/lib/
, но я получил ту же ошибку как OP. Все, что я должен был сделать, было выполнено sudo ldconfig -v
, я не должен был создавать /etc/ld.so.conf.d/opencv.conf
(из-за того, где библиотека была установлена).
– gromit190
2 March 2018 в 13:00
Чему-то нравится, могли бы запустить Вас, возможно:
TCHAR moduleName[MAX_PATH+1];
(void)GetModuleFileName(AfxGetInstanceHandle(), moduleName, MAX_PATH);
DWORD dummyZero;
DWORD versionSize = GetFileVersionInfoSize(moduleName, &dummyZero);
if(versionSize == 0)
{
return NULL;
}
void* pVersion = malloc(versionSize);
if(pVersion == NULL)
{
return NULL;
}
if(!GetFileVersionInfo(moduleName, NULL, versionSize, pVersion))
{
free(pVersion);
return NULL;
}
UINT length;
VS_FIXEDFILEINFO* pFixInfo;
VERIFY(VerQueryValue(pVersionInfo, const_cast<LPTSTR>("\\"), (LPVOID*)&pFixInfo, &length));
Осторожно! Использование FindResource...LockResource не является правильным. Иногда это работает (как в моей небольшой демо-программе), а иногда приводит к нарушению доступа (пример: производственный код, для которого я делал демо).
В документации по VerQueryValue() говорится, что вместо этого следует вызывать GetFileVersionInfoSize и GetFileVersionInfo. Раймонд Чен объясняет, см. http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215. aspx