ugrás a tartalomhoz

Oszály változók hivatkozása belső metódusokból

sirkalmi · 2010. Dec. 7. (K), 22.40
Sziasztok!

Hogyan lehet egy belső metódusból meghivatkozni egy osztály változót JavaScript-ben?

Pl:

TestClass = function() {
  this.ize = 'bigyo';

  this.valami = new Array();

  this.metodus = function() {
    dojo.forEach(this.valami, function(item) {
      //itt pl hogyan tudok hivatkozni az ize nevű osztály változóra?
    })
  }
}
Köszi a válaszokat!

sirkalmi
 
1

Változó

Poetro · 2010. Dec. 7. (K), 23.42
TestClass = function() {  
  var that = this;

  this.ize = 'bigyo';  
  
  this.valami = new Array();  
  
  this.metodus = function() {  
    dojo.forEach(this.valami, function(item) {  
      that.ize;  
    });
  }  
};
És ez nem csak osztályoknál, hanem bárhol máshol is használható, amikor mást jelent a this a függvényen belül, mint kívül.
3

Ez a JavaScript a

sirkalmi · 2010. Dec. 8. (Sze), 11.10
Ez a JavaScript a legbonyolultabb programozási nyelv amivel valaha dolgom akadt. Még az Assembly-t is jobban értettem. :-) A var that és a this.ize változók láthatóságában mi a különbség? Az egyik statikus a másik nem? Mindkettő csak a TestClass osztályon belül látszódik?
6

Closure / context

Poetro · 2010. Dec. 8. (Sze), 12.07
Az a különbség, hogy egy függvénynek minden futás esetében különbözhet a kontextusa. Azaz a this minden egyes futás esetén más lehet. Az, hogy mi legyen a this a függvény call illetve apply metódusával módosíthatod.

var x = {
  f: function (param1, param2) {
    console.log('param1: %s, param2: %s, this: %s', param1, param2, this);
  }
}
x.f('x1', 'x2')
f.call('argh', 'y1', 'y2');
f.apply(1, ['z1', 'z2']);
Kimenet:
param1: x1, param2: x2, this: [object Object]
param1: y1, param2: y2, this: argh
param1: z1, param2: z2, this: 1
És mivel a dojo.forEach függvény megváltoztatja a this jelentését a meghívott függvényen belül, ezért ha a függvényen kívüli this-re szeretnél hivatkozni, akkor azt el kell tárolni egy változóban.
8

Azt hiszem ezzel a válasszal

sirkalmi · 2010. Dec. 8. (Sze), 13.36
Azt hiszem ezzel a válasszal kerek a történet, köszönöm szépen!
9

Korrekció

Poetro · 2010. Dec. 8. (Sze), 14.46
Természetesen az előbbi példában a következő szerepelt:
x.f.call('argh', 'y1', 'y2');
x.f.apply(1, ['z1', 'z2']);
5

Azt hiszem rájöttem. A var

sirkalmi · 2010. Dec. 8. (Sze), 12.00
Azt hiszem rájöttem. A var változó az olyan mint Java-ban egy private osztály változó. Fenti kódot próbálgattam és sem az osztályon sem az osztály egy példányának a referenciáján keresztül nem érhető el a var that. Viszont, ha írok rá egy getter metódust akkor visszakapom az értékét.
A var that változót nem célszerűbb a constructorban inicializálni?
Meg azt nem értem, hogy ha a var that = this; ennyire kézenfekvő akkor miért nem szolgáltatja a nyelv automatikusan?
7

Változók

Poetro · 2010. Dec. 8. (Sze), 12.17
Mivel JavaScript-ben nincsenek osztályok ezért privát változók sincsenek. Viszont van hagyományos változó láthatóság, viszont ez a hagyományos nyelvekhez képest csak függvényen belül érvényes. Míg más nyelvekben minden blokkban hozhatunk létre új változókat, és azok csak az adott blokkban érvényesek, addig JavaScript alatt akár hol is hozunk létre egy változót egy függvényben az egész függvényben később használható lesz (kivéve ha a függvényben levő függvényben deklaráltuk, ami ekkor újabb láthatósági kört hoz létre).

Talán legjobb ha olvasol pár cikket a változó láthatóságról.
10

Function.prototype.bind

Poetro · 2010. Dec. 9. (Cs), 13.13
Az újabb JavaScript implementációk, amik már támogatják az 1.8.5-ös változatát a nyelvnek már tartalmazzák a Function.prototype.bind függvényt, amivel kényelmesen tudod módosítani egy függvény kontextusát.
TestClass = function() {  
  this.ize = 'bigyo';  
  
  this.valami = new Array();  
  
  function doStuff(item) {
    this.ize;
  }
  this.metodus = function() {  
    dojo.forEach(this.valami, doStuff.bind(this));
  }  
}
Természetesen ezt a függvényt könnyen megvalósíthatjuk akkor is, ha régebbi JavaScript verziót használunk:
if (!Function.prototype.bind)  
    Function.prototype.bind = function(context /*, arg1, arg2... */) {  
        'use strict';  
        if (typeof this !== 'function') throw new TypeError();  
        var _slice = Array.prototype.slice,  
            _concat = Array.prototype.concat,  
            _arguments = _slice.call(arguments, 1),  
            _this = this,  
            _function = function() {  
                return _this.apply(this instanceof _dummy ? this : context,  
                    _concat.call(_arguments, _slice.call(arguments, 0)));  
            },  
            _dummy = function() {};  
        _dummy.prototype = _this.prototype;  
        _function.prototype = new _dummy();  
        return _function;  
};  
11

Hmm, ki fogom próbálni ezt a

sirkalmi · 2010. Dec. 15. (Sze), 16.14
Hmm, ki fogom próbálni ezt a bind balhét! És a doStuff metódusnak hogyan adom át az értékeket, ha a bind-ot használom? A második eset annyira kaotikus nekem, hogy az kevésbé érdekel, inkább marad a var that = this; :-D
12

Nem értem a kérdést

Poetro · 2010. Dec. 15. (Sze), 16.52
A doStuff függvényt neked nem kell használni. A bind generál egy újabb függvényt, ami a doStuff függvényt használja úgy, hogy abban a this az lesz, amit megadsz a doStuff.bind hívásnál.
Írok egy egyszerű példát, ami hasonlít arra, amit a bind csinál, csak nem tud annyit, ezáltal sokkal egyszerűbb. jQuery-ben hasonlót a $.proxy csinál:
/**
 * Megváltoztatjuk egy függvény kontextusát, azaz a `this`-t.
 * @param {Function} fn
 *   A függvény, melyben meg akarjuk változtatni a kontextust.
 * @param {Object} context
 *   A függvény új kontextusa.
 * @returns {Function}
 *   Egy függvény, mely ugyan azt csinálja, 
 *   mint `fn` csak más benne a `this`.
 */
function bind(fn, context) {
  // Készítünk egy closure-t, azaz később is tudjuk, 
  // mi volt a context akár mikor is hívják meg a függvényt
  return function () {
    // A kapott függvényben a this meg fog egyezni a context-tel.
    return fn.apply(context, arguments);
  }
}

function doStuff(haha) {
  console.log(this.ize);
  console.log(haha);
}
var my = {ize : 'Én vagyok az izé'},
    myStuff = bind(doStuff, my);

myStuff('Működik');
Én vagyok az izé
Működik
2

Csak egy kósza tipp, mert nem

deejayy · 2010. Dec. 8. (Sze), 08.24
Csak egy kósza tipp, mert nem vagyok js májer, de mi történne, ha nevesítenéd azt az eljárást?
4

TestClass = function() {

sirkalmi · 2010. Dec. 8. (Sze), 11.58

TestClass = function() {  
  this.ize = 'bigyo';  
  
  this.valami = new Array();  
  
  this.metodus = function() {  
    dojo.forEach(this.valami, function(item) {  
      //jelenleg ezt a módszert alkalmazom de a referencia neve gyakran túl hosszú 
      //a névütközések elkerülése végett ezért kényelmetlen ezen keresztül 
      //hivatkozi rá. 
      //Meg bugyuta dolog is mert, ha megváltozik a referencia neve akkor írhatom át az teljes osztályt.
      referencia.ize; 
    })  
  }  
}

var referencia = new TestClass();