{"id":167,"date":"2008-03-07T12:17:34","date_gmt":"2008-03-07T11:17:34","guid":{"rendered":"http:\/\/pixy.cz\/pixynergia\/2008\/javascript-reference-na-matersky-objekt-v-event-handlerech\/"},"modified":"2008-03-07T17:21:20","modified_gmt":"2008-03-07T16:21:20","slug":"javascript-reference-na-matersky-objekt-v-event-handlerech","status":"publish","type":"post","link":"https:\/\/www.pixy.cz\/pixynergia\/2008\/03\/07\/javascript-reference-na-matersky-objekt-v-event-handlerech","title":{"rendered":"Javascript: Reference na mate\u0159sk\u00fd objekt v event handlerech"},"content":{"rendered":"\n<p>V\u00a0Javascriptu se mi \u010dasto st\u00e1v\u00e1, \u017ee m\u00e1m vytvo\u0159enou n\u011bjakou objektovou\nstrukturu a n\u011bjakou metodu takov\u00e9ho objektu chci pou\u017e\u00edt jako <em>ovlada\u010d\nud\u00e1losti (event handler)<\/em>. Ale zde nast\u00e1v\u00e1 probl\u00e9m v\u00a0tom, \u017ee\nkl\u00ed\u010dov\u00e9 slovo <code>this<\/code> odpov\u00edd\u00e1 p\u0159i vol\u00e1n\u00ed handleru ne\nmate\u0159sk\u00e9mu objektu, kter\u00e9mu pat\u0159\u00ed metoda, ale objektu, kter\u00fd vyvolal\nud\u00e1lost. P\u0159\u00edklad:<\/p>\n\n<pre class=\"js\"><code><span class=\"js-keywords1\">function<\/span><span\nclass=\"js-out\"> myObject(data) {\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.Data = data;\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.clickHandler = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">() {\n      alert(<\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">);\n      }\n   <\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span class=\"js-out\">   }\n\n<\/span><span\nclass=\"js-keywords1\">var<\/span><span class=\"js-out\"> obj = <\/span><span\nclass=\"js-keywords1\">new<\/span><span\nclass=\"js-out\"> myObject(data);\nsomeElement.onclick = obj.clickHandler;<\/span><\/code><\/pre>\n\n<p>Pokud nastane ud\u00e1lost <code>someElement.onclick<\/code>, zavol\u00e1 se sice\n\u201emetoda\u201c objektu <code>obj.clickHandler<\/code>, ale <code>this<\/code> bude\nv\u00a0tom okam\u017eiku znamenat objekt <code>someElement<\/code>, na kter\u00e9 ud\u00e1lost\nvznikla.<\/p>\n\n<p>\u010casto je v\u00a0t\u011bchto <em>handlerech<\/em> pot\u0159eba pracovat s\u00a0mate\u0159sk\u00fdm\nobjektem\u00a0\u2013 ostatn\u011b v\u011bt\u0161inou takov\u00e9to konstrukce p\u00ed\u0161eme coby n\u011bjak\u00e9\nobecn\u00e9 knihovny \u010di komplexn\u00ed struktury a chceme vyu\u017e\u00edvat hlavn\u00ed v\u00fdhody\nobjektov\u00e9ho programov\u00e1n\u00ed: tedy uzav\u0159enost a kontext, kdy si ka\u017ed\u00fd\npodobjekt spravuje sv\u00e9 v\u011bci, nem\u00edch\u00e1 se do jin\u00fdch \u010dinnost\u00ed a nikdo se\nzase nem\u00edch\u00e1 do t\u00e9 jeho. Tento nedostatek a chyb\u011bj\u00edc\u00ed zp\u011btn\u00e1 reference\nna mate\u0159sk\u00fd objekt se d\u00e1 r\u016fzn\u00fdmi zp\u016fsoby obej\u00edt. Nej\u010dast\u011bji dopln\u011bn\u00edm\nreference do potenci\u00e1ln\u00edch <em>event trigger\u016f<\/em>\u00a0\u2013 tedy objekt\u016f, kter\u00e9\nm\u016f\u017eou vyvolat danou ud\u00e1lost a p\u0159es kter\u00e9 se pak lze na mate\u0159sk\u00fd objekt\ndostat,\u00a0nap\u0159.:<\/p>\n\n<pre class=\"js\"><code><span class=\"js-comment\">\/\/ ...\n<\/span><span\nclass=\"js-out\">   <\/span><span class=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.clickHandler = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">() {\n      alert(<\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.owner);\n      }\n<\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span\nclass=\"js-out\">someElement.onclick = obj.clickHandler;\nsomeElement.owner = obj;<\/span><\/code><\/pre>\n\n<p>V\u00a0tomto p\u0159\u00edpad\u011b bude p\u0159i vyvol\u00e1n\u00ed ud\u00e1losti v\u00a0handleru hodnotou\n<code>this.owner<\/code> pr\u00e1v\u011b mate\u0159sk\u00fd objekt <code>obj<\/code>. Jenom\u017ee ne\nv\u017edycky je mo\u017en\u00e9 takov\u00e9 p\u0159i\u0159azen\u00ed ud\u011blat\u00a0\u2013 objekt\u016f je vytvo\u0159en\u00fdch\nmnoho a v\u00a0dan\u00e9m okam\u017eiku nev\u00edme, se kter\u00fdm se pr\u00e1v\u011b pracuje, nebo\n<em>event trigger<\/em> nen\u00ed dostupn\u00fd, abychom do n\u011bj mohli n\u011bco doplnit atd.\nTypicky se to st\u00e1v\u00e1 p\u0159i pou\u017eit\u00ed extern\u00edch knihoven a framework\u016f. Vezm\u011bme\njako p\u0159\u00edklad t\u0159eba <em>jQuery<\/em> a na\u010d\u00edt\u00e1n\u00ed dat p\u0159es\n<em>ajax<\/em>:<\/p>\n\n<pre class=\"js\"><code><span class=\"js-keywords1\">function<\/span><span\nclass=\"js-out\"> myObject() {\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.load = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">() {\n      $.get( <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.URL, <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.Params, <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onloadHandler );\n      }\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onloadHandler = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">(data) {\n     <\/span><span\nclass=\"js-comment\">\/* this.Data = data ??? *\/<\/span><span\nclass=\"js-out\">\n      }\n   <\/span><span class=\"js-comment\">\/\/ ...\n<\/span><span\nclass=\"js-out\">   }\n\n<\/span><span class=\"js-keywords1\">var<\/span><span\nclass=\"js-out\"> obj = [];\n<\/span><span class=\"js-keywords1\">for<\/span><span\nclass=\"js-out\"> (<\/span><span class=\"js-keywords1\">var<\/span><span\nclass=\"js-out\"> i=<\/span><span class=\"js-num\">0<\/span><span\nclass=\"js-out\">;i&lt;objCnt;i++) obj[i] = <\/span><span\nclass=\"js-keywords1\">new<\/span><span\nclass=\"js-out\"> myObject(data);\n<\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span\nclass=\"js-out\">obj[x].load();<\/span><\/code><\/pre>\n\n<p>Zde je po \u00fasp\u011b\u0161n\u00e9m na\u010dten\u00ed ajaxov\u00fdch dat op\u011bt coby <em>handler<\/em>\nzavol\u00e1na metoda <code>obj.onloadHandler<\/code>, ale tentokr\u00e1t v\u00a0n\u00ed\n<code>this<\/code> odpov\u00edd\u00e1 instanci intern\u00edho objektu\n<code>jQuery.ajax<\/code>, ke kter\u00e9mu se (slu\u0161n\u011b) nedostaneme a ned\u00e1 se do\nn\u011bj nic p\u0159id\u00e1vat. Instanc\u00ed <code>MyObject<\/code> je tak\u00e9 mnoho a nem\u016f\u017eeme\nzjistit, kter\u00fd to pr\u00e1v\u011b je. A\u00a0kone\u010dn\u011b vol\u00e1n\u00ed ajaxu je asynchronn\u00ed a\nm\u016f\u017ee jich prob\u00edhat sou\u010dasn\u011b n\u011bkolik, tak\u017ee n\u011bjak\u00e1 glob\u00e1ln\u00ed prom\u011bnn\u00e1\nn\u00e1s taky nezachr\u00e1n\u00ed.<\/p>\n\n<p>Je zde ale jedna v\u011bc, kter\u00e1 nen\u00ed na prvn\u00ed pohled v\u016fbec z\u0159ejm\u00e1: a\u010dkoli\nje doty\u010dn\u00fd <em>handler<\/em> vol\u00e1n ciz\u00edm objektem zvn\u011bj\u0161ku a je jakoby\n\u201evytr\u017een\u201c ze sv\u00e9ho kontextu v\u00a0mate\u0159sk\u00e9m objektu, po\u0159\u00e1d z\u016fst\u00e1v\u00e1\njeho \u201emetodou\u201c a p\u0159i vol\u00e1n\u00ed m\u00e1 jeho kontext a jmenn\u00fd prostor. Jsou zde\ntedy dostupn\u00e9 v\u0161echny prom\u011bnn\u00e9 definovan\u00e9 lok\u00e1ln\u011b v\u00a0r\u00e1mci mate\u0159sk\u00e9ho\nobjektu. A\u00a0d\u00e1 se toho vyu\u017e\u00edt:<\/p>\n\n<pre class=\"js\"><code><span class=\"js-keywords1\">function<\/span><span\nclass=\"js-out\"> myObject() {\n   <\/span><span\nclass=\"js-keywords1\">var<\/span><span class=\"js-out\"> thisObj = <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">;\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.load = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">() {\n      $.get( <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.URL, <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.Params, <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onloadHandler );\n      }\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onloadHandler = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">(data) {\n      thisObj.Data = data;\n      thisObj.doAnythingElse();\n      }\n   <\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span class=\"js-out\">   }<\/span><\/code><\/pre>\n\n<p>V\u00a0lok\u00e1ln\u00ed prom\u011bnn\u00e9 <code>thisObj<\/code> m\u00e1 objekt ulo\u017eenu referenci\ns\u00e1m na sebe, a tato reference bude dostupn\u00e1 i\u00a0<em>event handleru<\/em>\nzavolan\u00e9mu \u00fapln\u011b jin\u00fdm objektem. Bude zde platit, \u017ee <code>this<\/code> je\nobjekt, kter\u00fd vygeneroval ud\u00e1lost (<em>event trigger<\/em>), a\n<code>thisObj<\/code> je objekt\u00a0s\u00e1m.<\/p>\n\n<h3>Dopln\u011bn\u00ed:<\/h3>\n\n<p>D\u00edky Davidovi za skv\u011bl\u00fd n\u00e1pad v\u00a0koment\u00e1\u0159\u00edch! Je\u0161t\u011b jsem ho trochu\nupravil a vzniklo tak zat\u00edm nejlep\u0161\u00ed a form\u00e1ln\u011b asi nej\u010dist\u0161\u00ed\n\u0159e\u0161en\u00ed:<\/p>\n\n<pre class=\"js\"><code><span class=\"js-keywords1\">function<\/span><span\nclass=\"js-out\"> dynamicHandler(obj,method) {\n   <\/span><span\nclass=\"js-keywords1\">return<\/span><span class=\"js-out\"> <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">(){ method.apply(obj,arguments) };\n   }\n<\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span class=\"js-keywords1\">function<\/span><span\nclass=\"js-out\"> myObject() {\n   <\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span class=\"js-out\">   <\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">.load = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">() {\n      $.ajax({\n         url: <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.URL,\n         data: <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.Params,\n         success: dynamicHandler(<\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">,<\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onloadHandler),\n         error: dynamicHandler(<\/span><span\nclass=\"js-keywords1\">this<\/span><span class=\"js-out\">,<\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onerrorHandler)\n         });\n      }\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onloadHandler = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">(Data) {\n      <\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span class=\"js-out\">      }\n   <\/span><span\nclass=\"js-keywords1\">this<\/span><span\nclass=\"js-out\">.onerrorHandler = <\/span><span\nclass=\"js-keywords1\">function<\/span><span\nclass=\"js-out\">(XHR,ErrorString,Exception) {\n      <\/span><span\nclass=\"js-comment\">\/\/ ...\n<\/span><span\nclass=\"js-out\">      }\n   }<\/span><\/code><\/pre>\n\n<p>Jak je asi vid\u011bt, takhle to \u0159e\u0161en\u00ed funguje i\u00a0s\u00a0libovoln\u00fdm po\u010dtem\nparametr\u016f, co\u017e je docela d\u016fle\u017eit\u00e9. Standardn\u00ed event handlery sice\np\u0159ed\u00e1vaj\u00ed obvykle parametr jen jeden (event), ale nap\u0159. <em>jQuery<\/em> u\u017e\nvrac\u00ed parametr\u016f v\u00edce (t\u0159eba callback <code>$.ajax.error<\/code> vrac\u00ed\nargumenty a\u017e\u00a0t\u0159i).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>V\u00a0Javascriptu se mi \u010dasto st\u00e1v\u00e1, \u017ee m\u00e1m vytvo\u0159enou n\u011bjakou objektovou strukturu a n\u011bjakou metodu takov\u00e9ho objektu chci pou\u017e\u00edt jako ovlada\u010d ud\u00e1losti (event handler). Ale zde nast\u00e1v\u00e1 probl\u00e9m v\u00a0tom, \u017ee kl\u00ed\u010dov\u00e9 slovo this odpov\u00edd\u00e1 p\u0159i vol\u00e1n\u00ed handleru ne mate\u0159sk\u00e9mu objektu, kter\u00e9mu pat\u0159\u00ed metoda, ale objektu, kter\u00fd vyvolal ud\u00e1lost. P\u0159\u00edklad: function myObject(data) { this.Data = data; this.clickHandler &hellip; <a href=\"https:\/\/www.pixy.cz\/pixynergia\/2008\/03\/07\/javascript-reference-na-matersky-objekt-v-event-handlerech\" class=\"more-link\">Pokra\u010dov\u00e1n\u00ed textu <span class=\"screen-reader-text\">Javascript: Reference na mate\u0159sk\u00fd objekt v event handlerech<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,4],"tags":[],"class_list":["post-167","post","type-post","status-publish","format-standard","hentry","category-it","category-webdesign"],"_links":{"self":[{"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/posts\/167","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/comments?post=167"}],"version-history":[{"count":0,"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/posts\/167\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/media?parent=167"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/categories?post=167"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pixy.cz\/pixynergia\/wp-json\/wp\/v2\/tags?post=167"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}