How to modify the scope chain without `with` ?
Coroutines
coroutines at gmail.com
Mon Feb 15 09:13:03 UTC 2016
This post might be overly wordy. Sorry. It relates to the
functionality provided by the `with` keyword and why I think it's
important in the future.
I am currently rewriting a templating module that I think is very
useful for it's ability to turn a function in coffeescript syntax into
a sort of DSL - something that looks like this:
template = ->
doctype 5
html ->
head ->
title @title
body ->
div id: 'content', ->
if @posts?
for p in @posts
div class: 'post', ->
p p.name
div p.comment
form method: 'post', ->
ul ->
li -> input name: 'name'
li -> textarea name: 'comment'
li -> input type: 'submit'
For those not familiar with Coffeescript, "= ->" creates a function
with no arguments, the indented sub-block is the body of the function.
All of these things essentially compile into nested functions like:
html(head(title(this.title))
(not an exact translation)
Anyway, this library/module called (ck) exploits the little-used
`with` keyword. It creates a function like this:
function (scope, template) { with (scope) { template(); } }
So the template is just a series of functions that lookup within
`scope` for a function creating HTML. The problem is this module
(imo) wastefully creates a lot of closures to create the HTML tags.
It was my plan to create a Proxy object to use like: with (proxy) {
... } - so html() called within that `with` block would redirect
through the proxy to something like: makeTag('html', children...)
This does not work. Proxies as objects provided to `with` does not
work. I don't know if this is intended but I'm disappointed. `with`
itself is a keyword discouraged from use (it seems).
I am from Lua, where in Lua we have 2 variables called _ENV and _G.
In Javascript terms _G would point to `global` in node (the main
execution context/object). _ENV has no direct mapping to JS - it
would be the current context/object, which might not be _G anymore.
I wish it were possible to create objects that functions could run
within - you can seemingly only do this with the outmoded `with` or
with the 'vm' module in Node. People seem to discourage `with` and it
(iirc) is ignored in strict mode - and you can't use the `vm` module
in the browser.
I think there is a need for the ability to do this in ES7, and I wish
it were as simple as assigning an object to _ENV to change the
environment the function dereferences/resolves through.
Am I crazy or is this a good idea? The MDN posting on the `with`
keyword says you should just create a short reference to make use of
things - like: ck.p("this is a paragraph"); - but then this isn't as
natural as exploiting the context of what the function is running in
for the above `template` function. Again - I am NOT talking about how
`this` is defined but the outer scope/object. I wish scope lookup
were as simple as following a prototype chain. I wish I could easily
create a scope to run in from an object.
Would this be something useful - or is `with` just not in style
anymore? (I'm still mad I can't use a Proxy in with):
require('harmony-reflect');
let f = function() {
cats('abc');
dogs('123');
thisshouldjustlog('damnit');
};
let tmp = new Proxy({}, {
get: function() {
return console.log;
}
});
// disappointment abound
with (tmp) { f() };
More information about the es-discuss
mailing list