понедельник, 22 августа 2011 г.

Нестандартное использование Get и Set в Javascript


Многие в курсе, что в Javascript есть так называемые Getter'ы и Setter'ы. Это конструкции для отслеживания изменения значений свойств объекта, а так же возвращения этих значений. «С изнанки» объекта они выглядят как обычные функции:



var obj = {

   get value() {

     return 0;

   },

   set value(s) {

     alert ("Go screw yourself!")

   }

}




* This source code was highlighted with Source Code Highlighter.




Но раз это функции, их можно использовать как душе угодно!







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

function $(object) {

if(typeof(object)=="string"){object=document.getElementById(object)};

object.__defineGetter__("x",function(){

return (parseInt(object.style.left))

}),

object.__defineSetter__("x",function(n){

object.style.left = n + 'px'

}),

object.__defineGetter__("y",function(){

return (parseInt(object.style.left))

}),

object.__defineSetter__("y",function(n){

object.style.top = n + 'px'

})

}




* This source code was highlighted with Source Code Highlighter.




Теперь к кнопку с id «btn1» можно переместить, написав $("btn1").x = 56.



Но прелесть Getter'ов и Setter'ов не только в упрощении повседневных задач, типа работы с CSS. Их можно использовать даже для изменения концепции самого языка:



Например, следующий пример выведет сообщение на экран:



obj = {

  set message(s) {

  alert(s)

  }

}



obj.message = "Hello, World!"




* This source code was highlighted with Source Code Highlighter.




Страшно? По-моему, очень. Главное в этом деле не дойти до абсурда. Есть этому и математическое применение:



Например, у нас есть объект Obj, у которого есть свойство value, а также свойство sin. Обращаясь к свойству sin, мы получаем синус от value. Соль в том, что с помощью Setter'а можно сделать наоборот. Тогда после изменения sin, изменится и value. Одним словом, если sin==0.5, то value=Math.PI/6.



obj = {

 value: 0,

  get sin() {

  return Math.sin(this.value)

  }

  set sin(n) {

  this.value = Math.asin(n)

  }

}




* This source code was highlighted with Source Code Highlighter.




Стоит отметить, что решение не вполне кроссбраузерное. Если хотите портировать все это на ваш любимый Internet Explorer браузер, вам следует использовать __defineGetter__() и __defineSetter__(), либо методы, описанные здесь, и, в крайнем случае, здесь.



Но возможностей у Getter'ов и Setter'ов действительно много. Если скомбинировать все с тем же AJAX, можно добиться вполне кошерного вида вроде:



ajax.url = "script.php"

alert(ajax.result)




* This source code was highlighted with Source Code Highlighter.




Это, конечно, введет в замешательство некоторых программистов, привыкших к тому, что операция присваивания не делает ничего, кроме присваивания (собственно, как и операция взятия значения). Одно но, придется что-то сделать с методами без параметров, типа .Destroy(), ибо писать Obj.Destroy = true уж точно никто не будет. Есть идея сделать что-то вроде тайм-аута по тикам, т.е. отслеживать каждый get и set. Это значит, что Obj.Destroy = 5 уничтожит объект через 5 get/set операций. Но это, понятное дело, уже излишний креатив.









Источник: Хабрахабр - Ненормальное программирование
Оригинальная страница: Нестандартное использование Get и Set в Javascript

Комментариев нет:

Отправить комментарий