Javascript: String.prototype.namespace.method и this

Уже длительное время хочется сделать как-то так:

String.prototype.utils = {
        append : function(value){
            return this + value;
        }
}


Но к сожалению, на лицо проблема с this.

Если делать так:

String.prototype.utils = function(){
    
    var $this = this;
    return {
        append : function(value){
            return this + value;
        }
    }
}


Тогда каждый раз при 'one-'.utils().append('two') создается ненужный объект, да и не красиво это в конце концов.

Возможно ли переделать первый вариант так, что бы он работал?

'one-'.utils.append('two')

Спасибо заранее!
  • Вопрос задан
  • 4086 просмотров
Решения вопроса 1
barmaley_exe
@barmaley_exe
Нельзя, т.к. Ваш объект utils не будет знать о контексте (this для него что-то неопределенное).
Но если хочется извращений, то можно
 // https://gist.github.com/947203
(function(){
	var _utils = { // String.prototype.utils
			append : function(tail){
				return this + tail;
			}
		},
		utils = {}, // фронтэнд. на этот объект будут навешены геттеры.
					// на _utils геттеры вешать нельзя т.к. тогда мы не сможем (вроде как) добраться до методов
		self = null, // тут будет контекст
		generateGetter = function(fnc){ // это геттер
			return function(){ // геттер возвращает функцию
					return function(){ // которая при вызове возвращает
							// результат применения соответствующего метода с нужным контекстом
							return _utils[fnc].apply(self, arguments);
						};
				};
		};

	for(var prop in _utils){  // смотрим все методы _utils
		if(_utils.hasOwnProperty(prop)){
			// и назначаем для них геттеры для нашего фронтэнд объекта
			utils.__defineGetter__(prop, generateGetter(prop));
		}
	}

	// Геттер на String.prototype, который вернет наш презентационный объект
	// Когда кому-нибудь захочется обратиться к какому-нибудь методу этого объекта,
	// обьявленному в _utils, он попадет на геттер
	String.prototype.__defineGetter__('utils', function(){
		self = this;
		return utils;
	});
})();

// Пример
console.log('Hello'.utils.append(' World'));
console.log('Hello'.utils.append(' World')
                   .utils.append('!'));
(протестировано в Опере и Node.js)


Как видно, здесь активно используются геттеры, которые работают (вроде как) во всех современных браузерах, за исключением всего семейства IE.
Но самая большая печаль — ужасная неоптимальность этого кода. Вы только посмотрите на 3 (!!!) вложенных функции. И это я еще применил грязный хак с кешированием this в переменной self, дабы не создавать новых объектов.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы