Добавление настраиваемых свойств в функцию

Поиск подходящего ответа оказался трудным из-за существования многих других проблем, связанных с моими ключевыми словами, поэтому я задам этот вопрос здесь.

Как мы знаем, функции в javascript являются объектами и имеют свои собственные свойства и методы (точнее, функции, унаследованные от Function.prototype).

Я рассматривал возможность добавления настраиваемых свойств для одной функции (метода), давайте пропустим вопрос «почему?». часть и сразу переходите к коду:

var something = {
    myMethod: function () {
        if (something.myMethod.someProperty === undefined) {
            something.myMethod.someProperty = "test";
        }
        console.log(something.myMethod);
    }
}

При проверке с помощью проводника DOM Firebug свойство определяется, как ожидалось. Однако, поскольку я не считаю себя экспертом по javascript, у меня есть следующие вопросы:

  1. Можно ли считать этот метод «правильным» и соответствующим стандартам? Он работает в Firefox, но многие вещи работают должным образом в веб-браузерах и ни в коем случае не являются стандартами.
  2. Является ли такое изменение объектов путем добавления к ним новых свойств хорошей практикой?

person Przemek    schedule 21.12.2011    source источник
comment
Вы делаете это неправильно. Прочтите эту статью: packtpub.com/article/using-prototype-property- in-javascript Вы не можете добавить свойство x к функции fn следующим образом: fn.x = 'something'. Вам нужно использовать прототип.   -  person alessioalex    schedule 21.12.2011
comment
Что ж, это вроде работает и, как и в ответе @ nnnnnn, похоже, что это не неправильно. Не могли бы вы уточнить, почему?   -  person Przemek    schedule 21.12.2011
comment
@alessioalex - Вы определенно можете добавить свойство непосредственно в функцию. Это не всегда самый подходящий способ, но он (намеренно) является частью языка и отлично работает. (У него другая цель - добавление свойств к прототипу.) Тем не менее, спасибо за ссылку на статью, я сохраню ее, чтобы порекомендовать ее другим.   -  person nnnnnn    schedule 21.12.2011
comment
Присоединился, ссылка уже добавлена ​​в избранное.   -  person Przemek    schedule 21.12.2011
comment
См. stackoverflow.com/a/9526169/290182   -  person beldaz    schedule 02.03.2012


Ответы (10)


Немного сложно дать содержательный ответ на ваш вопрос, потому что вы как бы сказали: «Вот мое решение, все в порядке?» без объяснения, какую проблему вы пытаетесь решить (вы даже прямо сказали, что не собираетесь объяснять «почему»). Ваш код выглядит как действительный JavaScript, который будет работать, но он также выглядит как неоптимальный способ делать что-то.

Если вы объясните, чего вы на самом деле хотите достичь, вы можете получить несколько хороших предложений о лучших способах структурирования кода. Тем не менее, я дам вам какой-то ответ:

Можно ли считать этот метод «правильным» и соответствующим стандартам? Он работает в Firefox, но многие вещи работают должным образом в веб-браузерах и ни в коем случае не являются стандартами.

Функции - это объекты (как вы сказали), и поэтому к ним можно добавлять свойства. На самом деле это не проблема стандартов как таковая, поскольку это основная часть JavaScript, поддерживаемая всеми браузерами.

Является ли такое изменение объектов путем добавления к ним новых свойств хорошей практикой?

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

Сказав это, для меня на самом деле не имеет смысла добавлять свойства к функции myMethod, было бы более обычным добавлять другие свойства к вашему объекту something (ваша функция myMethod при правильном вызове будет иметь доступ к другим свойствам из something с помощью ключевого слова this).

Если вы используете функцию в качестве конструктора, обычно имеет смысл добавить методы к связанному прототипу и добавить свойства (не методы) к каждому экземпляру, но вы можете сделать либо, либо и то, и другое в зависимости от обстоятельств. (Обратите внимание на то, что «метод» - это, по сути, просто свойство, которое ссылается на функцию.)

Конкретный код, который вы показали, не добавляет свойств, он проверяет, существует ли свойство someProperty уже, и, если да, присваивает ему новое значение.

Возможно, вам будет полезно прочитать некоторые статьи, подобные этим, на MDN:

person nnnnnn    schedule 21.12.2011
comment
Ого, я не знаю, как я мог сделать такую ​​ошибку, я использовал !== вместо ===. Спасибо за ваш ответ. Эта проблема пришла мне в голову только как теоретическая, я также не вижу возможного (и удобочитаемого) использования для нее, просто исследую гибкость. - person Przemek; 21.12.2011
comment
@ Przemek, правда, ты не прав? Если бы вы использовали !==, условие никогда не было бы истинным, не так ли? - person Zyoo; 07.12.2014

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

Добавление собственных настраиваемых свойств к функции может выполняться разными способами, которые должны работать в каждом браузере.


Добавление собственных настраиваемых свойств к функции

Способ 1: добавление свойств во время выполнения функции:

var doSomething = function() {
    doSomething.name = 'Tom';
    doSomething.name2 = 'John';
    return 'Beep';
};

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : 
doSomething.name2 : undefined
doSomething() : Beep
doSomething.name : 
doSomething.name2 : John 

Способ 1 (альтернативный синтаксис):

function doSomething() {
    doSomething.name = 'Tom';
    doSomething.name2 = 'John';
    return 'Beep';
};

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : doSomething
doSomething.name2 : undefined
doSomething() : Beep
doSomething.name : doSomething
doSomething.name2 : John 

Способ 1 (второй альтернативный синтаксис):

var doSomething = function f() {
    f.name = 'Tom';
    f.name2 = 'John';
    return 'Beep';
};

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : f
doSomething.name2 : undefined
doSomething() : Beep
doSomething.name : f
doSomething.name2 : John 

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


Способ 2: добавление свойств после определения функции:

function doSomething() {
    return 'Beep';
};
    
doSomething.name = 'Tom';
doSomething.name2 = 'John';

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : doSomething
doSomething.name2 : John
doSomething() : Beep
doSomething.name : doSomething
doSomething.name2 : John 

Теперь вам не нужно сначала запускать свою функцию, прежде чем вы сможете получить доступ к своим свойствам. Однако недостатком является то, что ваши свойства кажутся отключенными от вашей функции.


Способ 3: превратите вашу функцию в анонимную:

var doSomething = (function(args) {
    var f = function() {
        return 'Beep';
    };
    for (i in args) {
        f[i] = args[i];
    }
    return f;
}({
    'name': 'Tom',
    'name2': 'John'
}));

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : 
doSomething.name2 : John
doSomething() : Beep
doSomething.name : 
doSomething.name2 : John 

Обернув вашу функцию анонимной функцией, вы можете собрать свои атрибуты в объект и использовать цикл для добавления этих атрибутов один за другим в анонимную функцию. Таким образом, ваши атрибуты будут более связаны с вашей функцией. Этот метод также очень полезен, когда ваши атрибуты нужно скопировать из существующего объекта. Однако недостатком является то, что вы можете добавлять только несколько атрибутов одновременно, когда вы определяете свою функцию. Кроме того, это не совсем приведет к появлению СУХОГО кода, если вы часто хотите добавлять свойства к функции.


Способ 4: добавьте к вашей функции функцию «расширения», которая одно за другим добавляет свойства объекта к себе:

var doSomething = function() {
    return 'Beep';
};
    
doSomething.extend = function(args) {
    for (i in args) {
        this[i] = args[i];
    }
    return this;
}

doSomething.extend({
    'name': 'Tom',
    'name2': 'John'
});

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : 
doSomething.name2 : John
doSomething() : Beep
doSomething.name : 
doSomething.name2 : John 

Таким образом, вы можете в любое время расширить несколько свойств и / или скопировать свойства из другого проекта. Однако, опять же, ваш код не СУХИЙ, если вы делаете это чаще.


Способ 5. Создайте общую функцию расширения:

var extend = function(obj, args) {
    if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
        for (i in args) {
            obj[i] = args[i];
        }
    }
    return obj;
}
    
var doSomething = extend(
    function() {
        return 'Beep';
    }, {
        'name': 'Tom',
        'name2': 'John'
    }
);

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : 
doSomething.name2 : John
doSomething() : Beep
doSomething.name : 
doSomething.name2 : John 

Функция генетического расширения позволяет использовать более СУХИЙ подход, позволяя вам добавлять объект или любой проект к любому другому объекту.


Способ 6. Создайте объект extendableFunction и используйте его для присоединения функции расширения к функции:

var extendableFunction = (function() {
    var extend = function(args) {
        if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
            for (i in args) {
                this[i] = args[i];
            }
        }
        return this;
    };
    var ef = function(v, obj) {
        v.extend = extend;
        return v.extend(obj);
    };

    ef.create = function(v, args) {
        return new this(v, args);
    };
    return ef;
})();

var doSomething = extendableFunction.create(
    function() {
        return 'Beep';
    }, {
        'name': 'Tom',
        'name2': 'John'
    }
);

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : 
doSomething.name2 : John
doSomething() : Beep
doSomething.name : 
doSomething.name2 : John 

Вместо использования общей функции «расширения» этот метод позволяет вам создавать функции, к которым прикреплен метод «расширения».


Способ 7. Добавьте функцию расширения к прототипу функции:

Function.prototype.extend = function(args) {
    if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
        for (i in args) {
            this[i] = args[i];
        }
    }
    return this;
};

var doSomething = function() {
    return 'Beep';
}.extend({
    name : 'Tom',
    name2 : 'John'
});

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : 
doSomething.name2 : John
doSomething() : Beep
doSomething.name : 
doSomething.name2 : John 

Большим преимуществом этого метода является то, что он делает добавление новых свойств к функции очень простым и СУХИМ, а также полностью ОО. Кроме того, это довольно удобно для памяти. Однако недостатком является то, что это не совсем надежное решение для будущего. В случае, если будущие браузеры когда-либо добавят встроенную функцию расширения в прототип функции, это может нарушить ваш код.


Способ 8: один раз запустить функцию рекурсивно, а затем вернуть ее:

var doSomething = (function f(arg1) {
    if(f.name2 === undefined) {
        f.name = 'Tom';
        f.name2 = 'John';
        f.extend = function(args) {
            if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
                for (i in args) {
                    this[i] = args[i];
                }
            }
            return this;
        };
        return f;
    } else {
        return 'Beep';
    }
})();

console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);

Выход :

doSomething.name : f
doSomething.name2 : John
doSomething() : Beep
doSomething.name : f
doSomething.name2 : John 

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


Добавление собственных настраиваемых свойств к объекту

Несмотря на все эти возможности, я бы все же не рекомендовал добавлять свойства в функцию. Намного лучше добавлять свойства к объектам!

Лично я предпочитаю одноэлементные классы со следующим синтаксисом.

var keyValueStore = (function() {
    return {
        'data' : {},
        'get' : function(key) { return keyValueStore.data[key]; },
        'set' : function(key, value) { keyValueStore.data[key] = value; },
        'delete' : function(key) { delete keyValueStore.data[key]; },
        'getLength' : function() {
            var l = 0;
            for (p in keyValueStore.data) l++;
            return l;
        }
    }
})();

Преимущество этого синтаксиса в том, что он позволяет использовать как открытые, так и частные переменные. Например, вот как вы делаете частную переменную data:

var keyValueStore = (function() {
    var data = {};
    
    return {
        'get' : function(key) { return data[key]; },
        'set' : function(key, value) { data[key] = value; },
        'delete' : function(key) { delete data[key]; },
        'getLength' : function() {
            var l = 0;
            for (p in data) l++;
            return l;
        }
    }
})();

Но вы говорите, что вам нужно несколько экземпляров хранилища данных? Без проблем!

var keyValueStore = (function() {
    var count = -1;
    
    return (function kvs() {
        count++; 
        return {
            'data' : {},
            'create' : function() { return new kvs(); },
            'count' : function() { return count; },
            'get' : function(key) { return this.data[key]; },
            'set' : function(key, value) { this.data[key] = value; },
            'delete' : function(key) { delete this.data[key]; },
            'getLength' : function() {
                var l = 0;
                for (p in this.data) l++;
                return l;
            }
        }
    })();
})();

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

var keyValueStore = (function() {
    var count = 0; // Singleton private properties
        
    var kvs = function() {
        count++; // Instance private properties
        this.data = {};  // Instance public properties
    };
    
    kvs.prototype = { // Instance public properties
        'get' : function(key) { return this.data[key]; },
        'set' : function(key, value) { this.data[key] = value; },
        'delete' : function(key) { delete this.data[key]; },
        'getLength' : function() {
            var l = 0;
            for (p in this.data) l++;
            return l;
        }
    };
        
    return  { // Singleton public properties
        'create' : function() { return new kvs(); },
        'count' : function() { return count; }
    };
})();

С помощью этого синтаксиса вы можете:

  • несколько экземпляров объекта
  • частные переменные
  • переменные класса

Вы используете это так:

kvs = keyValueStore.create();
kvs.set('Tom', "Baker");
kvs.set('Daisy', "Hostess");
var profession_of_daisy = kvs.get('Daisy');
kvs.delete('Daisy');
console.log(keyValueStore.count());
person John Slegers    schedule 22.12.2013
comment
Мне очень помогли! Спасибо за полезную информацию, приятель! - person Pankaj; 09.02.2018
comment
Слишком коротко, требует доработки. - person Haggra; 13.12.2019
comment
Вывод Способ 1 должен иметь тот же вывод, что и Способ 1 (альтернативный синтаксис). Кроме того, поскольку это очень полезные примеры, я думаю, что стоит добавить несколько слов для объяснения этого вывода, например, что doSomething.name выводит doSomething, поскольку Function.name является встроенным свойством, а doSomething.name2 - нет, но вызов doSomething() отменяет встроенное свойство. в name и определяет новое свойство name2. - person OfirD; 08.05.2020

"некромантинг" здесь, но я думаю, что на каждый важный вопрос нужны простые ответы:

Да и Да *

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

Создал несколько забавных примеров здесь и здесь. ЗДЕСЬ И ЗДЕСЬ


Думаю, стоит отметить, что вы, вероятно, не будете видеть это очень часто. большинство разработчиков, вероятно, не осознают, что это возможно. Некоторые люди без ума от каждой капли производительности ... "движки JavaScript оптимизируются на основе 'форма' объекта '... " бла-бла-бла ... но я думаю, вы можете следовать правилу, которое у вас есть для объектов, и все будет в порядке.

person Shanimal    schedule 18.07.2014

Прикрепление свойств к функциям - прекрасный (возможно, медлительный / хакерский) способ перегрузки оператора (), который, в свою очередь, обычно используется для реализации functors: Типы объектов, которые выполняют одну действительно важную работу, и все другие ее функции (если они есть) - это просто набор помощников. Вы также можете интерпретировать эти функторы как, по сути, функцию с состоянием, в которой состояние является общедоступным (например, большинство встроенных функций имеют частное состояние, то есть состояние из локальной области).

Этот JSFiddle демонстрирует, как мы можем использовать функцию с настраиваемыми свойствами для функции translator с дополнительными утилитами:

/**
 * Creates a new translator function with some utility methods attached to it.
 */
var createTranslator = function(dict) {
    var translator = function(word) {
        return dict[word];
    };

    translator.isWordDefined = function(word) {
        return dict.hasOwnProperty(word);
    };

    // Add more utilities to translator here...

    return translator;
};


// create dictionary
var en2deDictionary = {
    'banana': 'Banane',
    'apple': 'Apfel'
};

// simple use case:
var translator = createTranslator(en2deDictionary);
var pre = $('<pre>');
$("body").append(pre);

pre.append(translator('banana') + '\n');
pre.append(translator('apple') + '\n');
pre.append(translator.isWordDefined('w00t') + '\n');

Как видите, это идеально подходит для переводчика, единственной целью которого является перевод. Конечно, существует гораздо больше примеров этих типов объектов, но они далеко не так распространены, как типы с разнообразной функциональностью, такие как классические типы User, Animal Car и т. Д. К такого рода типам вы хотите добавлять настраиваемые свойства только в очень немногих случаях. Обычно вы хотите определить их как более полные классы, и чтобы их общедоступные свойства были доступны через this и prototype.

person Domi    schedule 09.05.2014

Я понимаю, что опоздал на несколько лет, но решил добавить этот пример - requirejs устанавливает свойство amd для функции define (), что очень удобно, поскольку шаблон UMD использует его для определения того, что определение (), которая находится в области видимости, на самом деле является функцией AMD define ().

Источник RequireJS: http://requirejs.org/docs/release/2.1.9/comments/require.js

Шаблон UMD, показывающий это использование: https://github.com/umdjs/umd/blob/master/amdWeb.js

person user456176    schedule 29.11.2013

Если вы просто хотите добавить настраиваемые свойства к функции, вам нужно только добавить эти свойства в Function.prototype. Например:

Function.prototype.SomeNewProperty = function () {//Do something awesome here...}
person Nitij    schedule 22.02.2015

Вполне допустимо добавлять свойства или методы к объекту функции. Это делается довольно часто. Примером этого является объект jQuery / $. Это функция, к которой прилагается довольно много методов.

Когда свойства добавляются к конструктору, они называются «статическими» свойствами и могут быть вызваны без экземпляра класса. например Object.create.

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

person AdamW    schedule 29.11.2016

Я согласен с тем, что это сложный вопрос, на который может быть несколько ответов, поэтому я предпочитаю привести другой пример:

Предположим, у вас есть JavaScript Array, заполненный генератором:

var arr = [...new Array(10).keys()];

то есть

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Теперь мы хотим сопоставить это с новым массивом такой же длины, применив некоторую функцию, чтобы мы могли использовать собственное свойство функции map:

arr = arr.map((value,index) => ++value)

Мы только что выполнили value=value+1 и вернулись, поэтому теперь массив будет выглядеть как

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Хорошо, теперь у нас должен быть JavaScript Object, например

var obj=new Object()

который был определен как предыдущий массив (по какой-то безумной причине):

arr.forEach((value,index) => obj[value]=value)

i.e.

{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}

На этом этапе мы не можем применить тот же метод map, поскольку он не определен для Object, поэтому мы должны определить его как новый prototype Object:

Object.defineProperty(Object.prototype, 'mapObject', {
      value: function(f, ctx) {
          ctx = ctx || this;
          var self = this, result = {};
          Object.keys(self).forEach(function(k) {
              result[k] = f.call(ctx, self[k], k, self);
          });
          return result;
      }
    });

На этом этапе мы могли бы поступить так же, как и раньше с массивом:

obj=obj.mapObject((value,key) => ++value )

так что у нас есть:

{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}

Как видите, мы обновили только значения:

[...Object.keys(obj)]
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

и мы можем вернуться к выходному массиву:

[...Object.keys(obj).map(k=>obj[k])]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Вот он в работе:

// Array.map
var arr = [...new Array(10).keys()];
console.log("array", arr)
arr = arr.map((value, index) => ++value)
console.log("mapped array", arr)
// new property
Object.defineProperty(Object.prototype, 'mapObject', {
  value: function(f, ctx) {
    ctx = ctx || this;
    var self = this,
      result = {};
    Object.keys(self).forEach(function(k) {
      result[k] = f.call(ctx, self[k], k, self);
    });
    return result;
  }
});

// Object.mapObject
var obj = new Object()
arr = [...new Array(10).keys()];
arr.forEach((value, index) => obj[value] = value)
console.log("object", obj)
obj = obj.mapObject((value, key) => ++value)
console.log("mapped object", obj)
console.log("object keys", [...Object.keys(obj)])
console.log("object values", [...Object.keys(obj).map(k => obj[k])])

person loretoparisi    schedule 27.10.2017

Возможное дополнение к отличному ответу Джона Слегерса

Неужели после Джона Слегерса:

Способ 2: добавление свойств после определения функции

Добавление Way 2.5

function doSomething() {
    doSomething.prop = "Bundy";
    doSomething.doSomethingElse = function() {
        alert("Why Hello There! ;)");

    };

    let num = 3;
    while(num > 0) {
        alert(num);
        num--;  
    }
}

sayHi();
sayHi.doSomethingElse();
alert(doSomething.prop);

var ref = doSomething;

ref();
ref.doSomethingElse();
alert(ref.prop);

Ввод как свойства «переменной», так и свойства функции для полноты, прямо в объявление функции. Таким образом, избегая того, чтобы его «отключили». Оставил внутреннюю работу функции по умолчанию (простой цикл), чтобы показать, что она все еще работает. Нет?

person brat    schedule 06.11.2018

test = (function() {
  var a = function() {
    console.log("test is ok");
  };
  a.prop = "property is ok";
  a.method = function(x, y) {
    return x + y;
  }
  return a
})()

test();
console.log(test.prop);
console.log(test.method(3, 4));

В качестве альтернативы вам нужно использовать геттеры и сеттеры

var person = {
  firstName: 'Jimmy',
  lastName: 'Smith',
  get fullName() {
    return this.firstName + ' ' + this.lastName;
  },
  set fullName(name) {
    var words = name.toString().split(' ');
    this.firstName = words[0] || '';
    this.lastName = words[1] || '';
  }
}
console.log(person.firstName);
console.log(person.lastName);
console.log(person.fullName);
person.fullName = "Tom Jones";
console.log(person.fullName);

person Zibri    schedule 18.03.2020