Function.name

Этот перевод не завершён. Пожалуйста, помогите перевести эту статью с английского

Read-only свойство name глобального объекта Function и его экзепляров содержит название функции созданное во время определения функции или присваивания ссылки на функцию переменной, свойству, аргументу и т. п. Для анонимных функций это свойство может иметь значение "anonymous" или пустую строку  "".

Интерактивные примеры размещены в GitHub репозитории. Если вы хотите добавить свои примеры, то клонируйте https://github.com/mdn/interactive-examples и пришлите пулл реквест.

Атрибуты свойстваFunction.name
Записываемое нет
Перечисляемое нет
Настраиваемое да

 

Заметьте, что в нестандартном, pre-ES2015 релизе configurable свойство было false

Примеры

Имя объявленной функции

Свойство name возвращает имя функции, либо пустую строку для анонимных функций:

function doSomething() {}

alert(doSomething.name); // выведет "doSomething"

Имя функции-конструктора

Функции, созданные синтаксисом new Function(...) или просто Function(...) создают  Function и имеют name "anonymous":​​​

(new Function).name; // "anonymous"

Предполагаемые имена функций

Переменные и методы могут предположить название анонимной функции из ее синтаксической позиции  (new in ECMAScript 2015).

var f = function() {};
var object = {
  someMethod: function() {}
};

console.log(f.name); // "f"
console.log(object.someMethod.name); // "someMethod"

Вы можете определить функцию с именем в function expression:

var object = {
  someMethod: function object_someMethod() {}
};
console.log(object.someMethod.name); // выведет "object_someMethod"

try { object_someMethod } catch(e) { console.log(e); }
// ReferenceError: object_someMethod is not defined

Вы не можете изменить имя функции, это свойство только для чтения:

var object = {
  // анонимная функция
  someMethod: function() {}
};

object.someMethod.name = 'otherMethod';
alert(object.someMethod.name); //someMethod

Для изменения name можно использовать Object.defineProperty().

Сокращенные имена методов

var o = {
  foo(){}
};
o.foo.name; // "foo";

Имена функций после байндинга

Function.bind() производит функцию, получающую имя "bound  и название самой функции.

function foo() {}; 
foo.bind({}).name; // "bound foo"

Имена функций для getters и setters

Когда используются get и set, "get" и "set" появятся в имени функции.

let o = { 
  get foo(){}, 
  set foo(x){} 
}; 

var descriptor = Object.getOwnPropertyDescriptor(o, "foo"); 
descriptor.get.name; // "get foo" 
descriptor.set.name; // "set foo";

Имена функций-классов

Можно использовать obj.constructor.name чтобы проверить "class" объекта (читайте предупреждение ниже):

function Foo() {}  // ES2015 Syntax: class Foo {}

var fooInstance = new Foo();
console.log(fooInstance.constructor.name); // logs "Foo"

Warning: Интерпретатор объявит встроенное Function.name свойство только если функция не имеет своего собственного свойства name (см.  9.2.11 of the ECMAScript2015 Language Specification). Однако, в ES2015 статичные методы перезаписывают OwnProperty конструкторов класса-функции (ECMAScript2015, 14.5.14.21.b + 12.2.6.9).

Таким образом, нельзя получить доступ к name любого класса со статичным свойством name()​​​​​​:

class Foo {
  constructor() {}
  static name() {}
}

Со static name() методом Foo.name больше не содержит название класса, но отсылает к функции name(). Приведенное выше определение класса в ES2015 будет вести себя в Chrome и Firefx как в  ES5:

function Foo() {}
Object.defineProperty(Foo, 'name', { writable: true });
Foo.name = function() {};

Пытаясь получить доступ к fooInstance с помощью fooInstance.constructor.name не даст название класса, но выведет метод name(). Пример:

let fooInstance = new Foo();
console.log(fooInstance.constructor.name); // logs function name()

Из ES5 syntax примера также видно, что в Chrome или Firefox статичное определение Foo.name становится записываемым (writable). Встроенное определение в отсутствии кастомного статичного методадоступно только для чтения:

Foo.name = 'Hello';
console.log(Foo.name); // logs "Hello" if class Foo has a static name() property but "Foo" if not.

Следовательно не ожидайте, что Function.name свойство будет всегда содержать имя класса.

Имена функций-символов

Если у Symbol объявляется имя, то название метода - это имя квадратных скобках.

let sym1 = Symbol("foo"); 
let sym2 = Symbol(); 
let o = { 
  [sym1]: function(){}, 
  [sym2]: function(){} 
}; 

o[sym1].name; // "[foo]"
o[sym2].name; // ""

JavaScript минифицированный

Warning: Будьте осторожны, используя Function.name и изменения source кода с помощью JavaScript compressors (minifiers) или обфускаторов. Эти инструменты часто используются, как встроенные в  JavaScript build pipeline, чтобы сократить размер билда перед деплоем в production. Такие трансформации часто изменяют имена функций.

Такой source code:

function Foo() {};
let foo = new Foo();

if (foo.constructor.name === 'Foo') {
  console.log("'foo' is an instance of 'Foo'");
} else {
  console.log('Oops!');
}

может быть сжат в:

function a() {};
let b = new a();
if (b.constructor.name === 'Foo') {
  console.log("'foo' is an instance of 'Foo'");
} else {
  console.log('Oops!');
}

В несжатой версии код выполняется ожидаемо "'foo' is an instance of 'Foo'". В то время, как в сжатой версии он ведет себя иначе. Если вы полагаетесь на Function.name, как в примере, то убедитесь, что pipeline не меняет код или не ожидайте от функции определенного имени.

Спецификация

Статус Комментарии
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'name' в этой спецификации.
Стандарт Изначальное определение.

Совместимость с браузерами

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung InternetNode.js
nameChrome Полная поддержка 15Edge Полная поддержка 14Firefox Полная поддержка 1IE Нет поддержки НетOpera Полная поддержка 10.5Safari Полная поддержка 6WebView Android Полная поддержка 1Chrome Android Полная поддержка 18Firefox Android Полная поддержка 4Opera Android Полная поддержка 11Safari iOS Полная поддержка 6Samsung Internet Android Полная поддержка 1.0nodejs Полная поддержка Да
Configurable: trueChrome Полная поддержка 43Edge Полная поддержка 14Firefox Полная поддержка 38IE Нет поддержки НетOpera Полная поддержка 30Safari Нет поддержки НетWebView Android Полная поддержка 43Chrome Android Полная поддержка 43Firefox Android Полная поддержка 38Opera Android Полная поддержка 30Safari iOS Нет поддержки НетSamsung Internet Android Полная поддержка 4.0nodejs ?
Inferred names on anonymous functionsChrome Полная поддержка 51Edge Частичная поддержка 14
Замечания
Частичная поддержка 14
Замечания
Замечания Names for functions defined in a dictionary are properly assigned; however, anonymous functions defined on a var/let variable assignment have blank names.
Firefox Полная поддержка 53IE Нет поддержки НетOpera Полная поддержка 38Safari Полная поддержка 10WebView Android Полная поддержка 51Chrome Android Полная поддержка 51Firefox Android Полная поддержка 53Opera Android Полная поддержка 41Safari iOS Полная поддержка 10Samsung Internet Android Полная поддержка 5.0nodejs ?

Легенда

Полная поддержка  
Полная поддержка
Частичная поддержка  
Частичная поддержка
Нет поддержки  
Нет поддержки
Совместимость неизвестна  
Совместимость неизвестна
Смотрите замечания реализации.
Смотрите замечания реализации.