JS: context geven aan een new Function()

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Hallo

Ik heb voor mijn plezier een kleine lib gemaakt die Linq-like operaties mogelijk maakt op collecties.
Voor de fun heb ik ook de mogelijkheid geïmplementeerd om te werken met een expressie. (verhoogd mijns inziens ook dikwijls de leesbaarheid omdat je de functiediarree wat kan inperken op het toplevel)
Voorbeeld:
personArray.where(function(x) { return x.name == "John"; } );
OF met expressie
personArray.where("x => x.name == 'John'");

Nu de vraag waar op ik niet direct een bevredigend antwoord vindt: hoe kan ik ervoor zorgen dat mijn nieuwe functie (adhv de expressie) de context krijgt van de locatie waar ze wordt opgeropen.
Voorbeeld (werkt niet aangezien de where functie een nieuwe functie genereert en deze de randomname variabele niet kent)
var randomname = "John";
personArray.where("x => x.name == randomname");

Bovenstaande werkt natuurlijk wél als ik gewoon een functie meegeef als argument.

Ik dacht ergens gelezen te hebben dat ik op geen enkele manier dit kan bewerkstelligen, maar ben hier niet zeker van. Call en apply lijken mij ook niet te bieden wat ik wil, of ben ik hier verkeerde besluiten aan het nemen.

Iemand een idee?

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 12-07 22:24
SideShow schreef op dinsdag 11 december 2012 @ 13:22:
Nu de vraag waar op ik niet direct een bevredigend antwoord vindt: hoe kan ik ervoor zorgen dat mijn nieuwe functie (adhv de expressie) de context krijgt van de locatie waar ze wordt opgeropen.
Dat kun je niet. Closed over variabelen zijn in de scope waar de functie gemaakt wordt, niet waar de string literal staat waarmee de functie gedefinieerd gaat worden.

Overigens is het een erg slecht idee om op deze manier lambdas te definiëren om over collecties te itereren. Functies die met de Function constructor dynamisch aangemaakt worden zijn vele malen trager dan normaal gedefinieerde functies. (Soms zelfs tot 20x trager; en dat is onder de V8 engine van Google.)

Als je echt lambda notatie wilt hebben, gebruik dan een pre-processor zoals TypeScript. (Heb je ook gelijk type hinting en inference.)

[ Voor 6% gewijzigd door R4gnax op 12-12-2012 10:58 ]


Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
TypeScript en co vind ik eigenlijk ook niet zo aantrekkelijk. Ik leer liever gewoon javascript.
De traagheid van de functie constructor valt volgens mij wel mee, omdat er in de where method slecht 1 keer een functie wordt gemaakt, de daarop volgende iteratie gebruikt vervolgens één en dezelfde functie.

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 12-07 22:24
SideShow schreef op woensdag 12 december 2012 @ 12:47:
TypeScript en co vind ik eigenlijk ook niet zo aantrekkelijk. Ik leer liever gewoon javascript.
De traagheid van de functie constructor valt volgens mij wel mee, omdat er in de where method slecht 1 keer een functie wordt gemaakt, de daarop volgende iteratie gebruikt vervolgens één en dezelfde functie.
Voor iemand die 'liever gewoon JavaScript leert' ben je anders druk bezig om de taal te misbruiken om constructies te maken die niet tot 'vanilla' JavaScript behoren. Misschien is het je ontschoten, maar TypeScript is gewoon JavaScript, al dan niet wat JavaScript over een jaar of 2 zal zijn: TypeScript is gebaseerd op zaken die nu al in de ECMAScript Harmony modules terug te vinden zijn en de intentie is ook om TypeScript up-to-date te houden met deze specificaties. Het is dus niet een totaal andere taal met een andere syntax, zoals CoffeeScript of Dart dat zijn.

Verder heeft de traagheid van de fucntie constructor tegenwoordig voornamelijk te maken met de optimalisaties die de javascript engine kan maken in de context van statisch aangeleverde vs. dynamisch opgebouwde code. En de prijs daarvoor betaal je elke keer dat de functie gedraaid wordt; niet slechts die enkele keer dat de functie gebouwd wordt.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-07 03:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

SideShow schreef op dinsdag 11 december 2012 @ 13:22:
(verhoogd mijns inziens ook dikwijls de leesbaarheid omdat je de functiediarree wat kan inperken op het toplevel)
Hoezo verhoogt dat de leesbaarheid / onderhoudbaarheid? Je hebt geen syntax highlighting in de string, en geen refactor mogelijkheden. Geknoei met strings is gewoon ranzig en zorgt alleen maar voor problemen. En zo heel verbose is de function expression syntax van javascript nou ook weer niet.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
var item = items.first("x => x.id == " + myId);
Toch leesbaar vind ik

Dat javascript binnen 2 jaar een type safe script wordt, is natuurlijk wel een heel sterke uitspraak.
Dat zou ik trouwens niet willen.

Volgens mij vervalt de traagheid van 1 keer een new Function() uit te voeren, in het niets bij de gemiddelde ajax request en response time...

Verder de volgende tests:
for (var i = 0; i < 10000; i++) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].first('x => x == 4')
Dit inderdaad redelijk traag (1.5 seconde hier), maar ... je hebt het dan ook 10000 keer gedaan ...

for (var i = 0; i < 10000; i++) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].first(function(x) { return x == 4; } )
Dit is gewoon blazing fast...

var test = new Function("x", "return x == 4");
for (var i = 0; i < 10000; i++) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].first(test)
Evenzeer blazing fast, waardoor ik de opmerking van R4gnax niet echt begrijp ...

Maar, de vraag was dus als je de context kan meegeven, en het antwoord blijkt dus inderdaad negatief

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-07 03:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

SideShow schreef op donderdag 13 december 2012 @ 11:12:
var item = items.first("x => x.id == " + myId);
Toch leesbaar vind ik
Ja als je gewoon niet ingaat op mijn argumenten en zelf niet eens argumenten aandraagt waarom jij dat vindt dan heeft de discussie ook niet veel nut he.
Dat zou ik trouwens niet willen.
Waarom niet?
• Code documenteert zichzelf beter
• Fouten kunnen tijdens compile-time al worden gerapporteerd

[ Voor 18% gewijzigd door .oisyn op 13-12-2012 11:26 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 17-07 11:44

Bosmonster

*zucht*

In Js is het gebruikelijker juist hier callback functies voor te gebruiken. Neem bijvoorbeeld de String.replace functie, die ook een custom replace-functie accepteert. Of de Array.sort-functie, die een custom sorterings-functie accepteert.

Dat is veel flexibeler, sneller en herbruikbaarder, dan proberen je eigen string-format te gaan bedenken, waar je ook weer een eigen parser voor moet ontwikkelen (of gaan evalueren...). Met alle nodige bugs (xss, etc) en documentatie tot gevolg..

Je collega's zullen je dankbaar zijn ;)

[ Voor 28% gewijzigd door Bosmonster op 13-12-2012 11:31 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
SideShow schreef op donderdag 13 december 2012 @ 11:12:
Dat javascript binnen 2 jaar een type safe script wordt, is natuurlijk wel een heel sterke uitspraak.
Dat is nergens beweerd. Wel dat Typescript "vooruitloopt" op zaken die in aankomende versies van ECMAScript er toch aan zitten te komen. Uiteindelijk zak Typescript dus (deels) 'convergeren' naar ECMAScript V<something> en waarschijnlijk daarna niet veel meer dan static typing toevoegen.
In this sense TypeScript is a preview of what to expect of ECMAScript 6.
...
A unique aspect not in the proposal, but added to TypeScript, is optional static typing
...
This is optional and can be ignored to use the regular dynamic typing of Javascript.
Emphasis mine.
.oisyn schreef op donderdag 13 december 2012 @ 11:32:
[...]

Dat is ook wat ie probeert te bewerkstelligen, alleen is hij het niet eens met de syntax van function expressions in Javascript. De C# lambda notatie is veel minder verbose. Maar dat betekent niet dat dat geen "callbacks" zijn.
Psies; ik zou dan, als ik dan toch m'n zin wou hebben, eerder gaan voor een Typescript-achtige oplossing. Gewoon iets bouwen dat "compiled" naar JS net zoals Typescript dat doet.

[ Voor 27% gewijzigd door RobIII op 13-12-2012 11:35 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-07 03:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Bosmonster schreef op donderdag 13 december 2012 @ 11:28:
In Js is het gebruikelijker juist hier callback functies voor te gebruiken.
Dat is ook wat ie probeert te bewerkstelligen, alleen is hij het niet eens met de syntax van function expressions in Javascript. De C# lambda notatie is veel minder verbose. Maar dat betekent niet dat dat geen "callbacks" zijn.

[ Voor 6% gewijzigd door .oisyn op 13-12-2012 11:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
.oisyn schreef op donderdag 13 december 2012 @ 11:25:

Waarom niet?
• Code documenteert zichzelf beter
• Fouten kunnen tijdens compile-time al worden gerapporteerd
Dynamische talen hebben toch gewoon hun plaats?

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 12-07 22:24
SideShow schreef op donderdag 13 december 2012 @ 11:12:
Verder de volgende tests:
for (var i = 0; i < 10000; i++) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].first('x => x == 4')
Dit inderdaad redelijk traag (1.5 seconde hier), maar ... je hebt het dan ook 10000 keer gedaan ...

for (var i = 0; i < 10000; i++) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].first(function(x) { return x == 4; } )
Dit is gewoon blazing fast...

var test = new Function("x", "return x == 4");
for (var i = 0; i < 10000; i++) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].first(test)
Evenzeer blazing fast, waardoor ik de opmerking van R4gnax niet echt begrijp ...
Ja, laten we even tegen een zeer triviale value comparison gaan testen en dat dan representatief noemen voor real-world scenario's en alle mogelijke vormen van code optimalisatie die de JIT compiler al dan niet toe zou kunnen passen. |:(

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Mja, meestal zijn collections en client side view models niet echt rocket sience inderdaad.
Het was dan ook mijn bedoeling om simpele zaken te doen, en niet 50 regels code als string mee te geven...

[ Voor 37% gewijzigd door SideShow op 13-12-2012 13:48 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-07 03:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

SideShow schreef op donderdag 13 december 2012 @ 12:52:
[...]

Dynamische talen hebben toch gewoon hun plaats?
Het blijft toch gewoon een dynamische taal?

Daarnaast weet je wederom geen argumenten op tafel te leggen, chapeau :). Goed dan: wat is de reden dat dynamische talen dan gewoon hun plaats hebben?

En laat ik het omdraaien: waarom denk je dat er überhaupt features als type hinting in PHP en dus nu ook strict typing in Javascript wordt geïmplementeerd? Omdat er geen vraag naar is?

[ Voor 20% gewijzigd door .oisyn op 13-12-2012 14:37 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1