Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Установить имя конструктора (https://javascript.ru/forum/misc/23203-ustanovit-imya-konstruktora.html)

Андрей Параничев 15.11.2011 23:17

Установить имя конструктора
 
Возможно ли каким-то образом установить произвольное имя конструктору, который является function expression?
Или только генерируя function declaration и вызывать его через eval?

Добавлено:
Немного лажанул с терминологией. Суть в том, что мне нужно сменить имя любой функции, не важно expression или declaration. Это возможно? Установка свойства "name" естественно не помогает и даже установка геттера на name. Скорее всего, как я понял, это сделать невозможно.

DjDiablo 16.11.2011 01:39

Функции и конструкторы в javaScript по сути все безымянны, когда мы создаём функцию, мы обычно создаём ещё и ссылку на функцию И имеем дело в дальнейшем с именами переменных ссылок, но ни как не с именами функций или конструторов.

a=function(x,y){
        alert(x+y);
    }
    b=a; //дадим функции имя b
    c=a; //дадим функции имя c
    
    a(1,1); // вызовем функцию с именем а

    delete a; // УДАЛИМ первое имя функции

    b(1,2); // второе имя функции (работает несмотря на то что первое имя исчезло)
    c(2,3); // третье имя функции (работает несмотря на то что первое имя исчезло)


Декларативная запись даст тот же эффект.

function a(x,y){
        alert(x+y);
    }
    b=a; //дадим функции имя b
    c=a; //дадим функции имя c
    
    a(1,1); // вызовем функцию с именем а

    delete a; // УДАЛИМ первое имя функции

    b(1,2); // второе имя функции (работает несмотря на то что первое имя исчезло)
    c(2,3); // третье имя функции (работает несмотря на то что первое имя исчезло)


уневерсальный метод меняющий "имя функции" в обьекте context.

// метод
function changeName (context,oldname,newname) {
        context[newname]=context[oldname];
        delete context[oldname]; // удаляем старое имя из обьекта
}

// проверка
test={
     functest: function(){
         alert ("привет");
     }
};

// заменим старое имя functest, на новое testNewName
changeName(test, "functest", "testNewName");

// обратимся к функции по новому имени
test.testNewName();


функция даже сама может поменять своё имя, а при необходимости даже самоликвидироваться, унечтожив последнюю ссылку на себя.
test={
     functest: function(){
         alert ("привет");
         // если мы ещё не меняли то поменяем имя функции      
         if (this.functest) {
               this["newnamefunc"]=this.functest;
               delete this.functest; // удалим старое имя функции
         }
                
     }
}

// обратимся к функции, функция сменит своё имя
test.functest();

// обратимся к функции по новому имени
test.newnamefunc();

// попробуем обратится по старому имени, и получим ошибку
test.functest();

Kolyaj 16.11.2011 09:47

Цитата:

Сообщение от DjDiablo
Функции и конструкторы в javaScript по сути все безымянны

Имя у них как раз есть. Просто это не то же самое, что ссылка на функцию, хотя зачастую они совпадают.
var x = function y() {};
alert('Переменная x: ' + typeof x);
alert('Переменная y: ' + typeof y);
alert('Имя функции: ' + x.name);

Pavel M. 16.11.2011 10:45

Цитата:

Сообщение от Kolyaj
Имя у них как раз есть.

по моему .name это не стандартное свойство, лучше им не пользоваться, в ie9, например, x.name не заработало

DjDiablo 16.11.2011 11:53

x.name - константа, помнит имя указанное в момент создания функции.
наличие имени функции в x.name - это не гарант того что функцию можно вызвать по этому имени.
Ума не могу приложить как можно использовать эту историческую справку :)
а так да, в некоторых браузерах типо имя :D

Kolyaj 16.11.2011 11:59

Цитата:

Сообщение от DjDiablo
наличие имени функции в x.name - это не гарант того что функцию можно вызвать по этому имени.

А где было сказано обратное?


Цитата:

Сообщение от DjDiablo
Ума не могу приложить как можно использовать эту историческую справку

Какую справку?

DjDiablo 16.11.2011 12:35

Цитата:

А где было сказано обратное?
Я просто часто сравниваю с другими языками. К примеру c тем же с/c++
строка void test(){ } это гарант в c/c++ того что я всегда смогу вызвать функцию по имени test, в javaScript нет таких гарантий. Нечего другого я сказать не хотел, это не было возражением тебе.

Цитата:

Какую справку?
Это была образная речь, попытка поиска аналогии в реальном мире.
Если раньше человека звали Вася, а после операции и смены паспорта Василиса :) То справка из паспортного стола о старом имени, помоему очень напоминает значение св-ва name, данное функции при рождении.

Мне кажется или мы флудить начинаем :D

Андрей Параничев 16.11.2011 23:01

Вызов тут не причем. Речь идет только о том, чтобы из this.constructor.name получить имя конструктора. И при псевдо-статическом наследовании получить в .name нужное имя. Так получается, то единственный способ гарантировать это - создавать конструктор с именем.

Но в моей задаче пришлось решить это дело созданием незащищенной constructor.__name__, которая берется из constructor.name или аргумента. В общем не самое красивое решение, но для моей задачи подойдет: мне нужно просто именовать модули в глобальном режиме. Единственный способ это имя конструктора, поскольку мне нужна совместимость с синтаксическим сахаром, генерируемым через CoffeeScript.

Целостность системы у меня отдельно проверяется, так что существование одинаковых имен для меня не проблема.

Kolyaj 17.11.2011 10:09

В IE у функций нет name.

Ну и не могу не заметить, что решение кривое. Точнее задача в рамках JS кривая, поэтому и решение кривое.


Часовой пояс GMT +3, время: 02:25.