I'm reading a textbook of the JavaScript language. And while I'm studying the closure topic, I came up with the following question.
Considering this function:
function foo() {
extractPropsToCurrentContext({'prop1' : 'hello', 'prop2' : 123});
}
I want the result of the above code, equals to:
function foo() {
var prop1 = 'hello';
var prop2 = 123;
}
So, my question is, how to implement the function extractPropsToCurrentContext(/* Object */) ?
Just to clarify, I want to extract those properties of the object into the execution context, not under the 'this' pointer. (So, those extracted props should be private inside that function).
Another thing to clarify, you can't assume the foo will be invoked with 'new'. (like new foo())
Update:
I mean, is there any possibility that we could use any hacky tricks to detour the restriction of browser, to get closer to the result we want? Like, years ago, we invented JSONP for cross-domain, long-pulling for message pushing, etc?
If we want to, we can dynamically change the execution context of any method by using either call() or apply(). Both of these functions can be used to bind the "this" keyword to an explicit context.
One way is to add a property using the dot notation: obj. foo = 1; We added the foo property to the obj object above with value 1.
The Execution Context contains the code that's currently running, and everything that aids in its execution. During the Execution Context run-time, the specific code gets parsed by a parser, the variables and functions are stored in memory, executable byte-code gets generated, and the code gets executed.
As the Function object is a predefined object in JavaScript, it has methods and properties associated with it. Two of these methods are call() and apply() . Using these methods on a Function object allows you to set the context of that function – that is, what the “ this ” keyword refers to.
I want to extract those properties of the object into the execution context
An execution context actually consists of three things:
the ThisBinding
, which you said you didn't want to alter or extend.
the VariableEnvironment
, which holds the declared variables and functions. This is what your equal code would change. You can alter it with the following hack:
function getVariableDeclaration(obj) {
return "var " + Object.keys(obj).map(function(name) {
return name + " = " + JSON.stringify(obj[name]);
}).join(",\n ") + ";";
}
function foo() {
eval(getVariableDeclaration({'prop1' : 'hello', 'prop2' : 123}));
debugger;
}
foo();
However, this works only in non-strict mode. Check §10.4.2 for details. Also, this hack currently is restricted to JSON-serialisable values, it would get a lot uglier if you needed to assign arbitrary values - eval
must be used in the environment that you want to alter.
The LexicalEnvironment
, which holds the current identifier bindings (and might change during execution in contrast to the VariableEnvironment
). This is not exactly what you might want, but it can be modified very easily via the with
Statement:
function foo() {
with ({'prop1' : 'hello', 'prop2' : 123}) {
debugger;
}
}
foo();
Again, it does not work in strict mode. See §12.10 and §10.2.2.3 on how it works and shadows other bindings.
As you can see, strict mode prohibits any changes to a (non-global) execution context, as this makes bindings non-static and non-optimisable. Most code becomes harder to understand as well, so this is in general considered a bad practise.
It's fine to ponder about such hacks from an academic viewpoint (to understand the workings of the language), but you should never use them in production. Whatever you have in mind that would require such techniques, there are better solutions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With