Toon posts:

[js] function scope verleggen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Dit werkt uiteraard:
JavaScript:
1
2
3
4
5
6
7
8
  foo = function() {
    return bar();
  }
  bar = function() {
    return 'something';
  }

  window['foo']();


Maar nu wil ik een zooi functies runtime genereren, afhankelijk van user input (new Function(...)). Om te zorgen dat die niet global draaien en vanalles kunnen verzieken wil ik ze dus in een object duwen en daar laten draaien.
Ik heb de volgende constructie

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
function Sandbox() {
  this.foo = function() {
    return bar();
  }
  this.bar = function() {
    return 'something';
  }
}
var s = new Sandbox()

s['foo']();

probleem is nu dat foo() bar() aan moet roepen, maar die is nu niet meer bekend. Wat ik nu wil is niet de functies zelf aanpassen, want die volgen uit user input, maar de manier van aanroepen van foo(). Ik dacht dus in eerste instantie aan iets als:
JavaScript:
1
s[foo].apply(s);

maar dan kent ie bar() nog steeds niet omdat ie dat als globale functieaanroep blijft zien.
Hoe kan ik er voor zorgen dat bar() in foo() gezien wordt als locale aanroep? Dus als ware het this.bar()?

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 05-11 19:33
Kun je vanuit foo niet gewoon this.bar(); doen? Anders zou je ook dit kunnen doen:
JavaScript:
1
2
3
4
5
6
7
8
this.foo = function()
{
    var self = this;
    return function()
    {
        self.bar();
    };
};

Of begrijp ik je probleem niet goed?

Noushka's Magnificent Dream | Unity


Verwijderd

Topicstarter
je begrijpt het niet goed :)
foo() en ook bar() worden door de user gemaakt. Ik heb ze voor het gemak als functies in het object gezet, maar ze worden aangemaakt via
JavaScript:
1
s[funcName] = new Function(funcBody);

waar funcName en funcBody door de user ingegeven worden. In het geval van foo() is de body dus de string "return bar()"

Ik kan op zich wel die funcBody string door de molen gooien en overal "this." voorplakken, maar eigenlijk wil ik dit dus buiten de functies oplossen, door een scope te definieren op de een of andere manier

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 05-11 19:33
Het lijkt er idd. op dat de functie in globale scope wordt aangemaakt en dat lokale variabelen daarbij niet te bereiken zijn. Ik denk dat er niets anders op zit dan de code aan te passen voordat je er een functie van maakt.

Noushka's Magnificent Dream | Unity


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Ik kom hierop uit maar kan me niet aan de indruk onttrekken dat dit toch wel wat ranzig is :P
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function Sandbox()
{
    this.text = 'something';
}
Sandbox.prototype =
{
    bar: function()
    {
        return this.text;
    },
    execute: function(funcname)
    {
        //-- import methods
        var bar = this.import_method(this.bar);

        var callable = eval('function(){'+this[funcname]+'}');

        return callable.call(this);
    },
    import_method: function(method)
    {
        var self = this;

        return function()
        {
            return method.call(self);
        }
    }
}

var s = new Sandbox();

s['foo'] = 'return bar()';
var result = s.execute('foo');
alert(result);

Intentionally left blank


Verwijderd

Topicstarter
woei, met die dingen van jou moet ik altijd 3x kijken wat het nu eigenlijk doet...

klopt het wat ik zeg?
- je zorgt ervoor dat de functie (this.bar) in een variabele (bar) wordt geladen binnen de scope van de execute method
- je maakt een functie aan met een body die door de user gegeven is (return bar())
- je voert die functie uit vanuit de scope van het execute method (waarin bar dus bestaat)

probleem wat ik heb is dat ook bar() door de user gemaakt wordt. Er zijn dus een hoop functies gecreëerd die mekaar allemaal direct aanroepen. Dat gaat goed als ik die functies allemaal globale functie maak, dus van window, maar niet als ik ze als method in een ander object hang (sandbox)

Iets wat ik me net bedacht is een iframe aanmaken, document maken en daar de boel lekker globaal laten doen, maar het moet toch makkelijker kunnen lijkt me zo

wel weer wat geleerd (dat eval iets returned bijvoorbeeld)

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Door een reference naar bar in een local variabele te stoppen en in diezelfde scope de user-defined code te evalueren creëer ik een closure :)
De beste manier om je sandbox-probleem op te lossen lijkt me echter toch:
JavaScript:
1
userdefined_js = userdefined_js.replace(/([};\s]|^)function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/, 'var $2 = function');

;)

Intentionally left blank

Pagina: 1