Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add properties to the current execution context dynamically in JavaScript?

Tags:

javascript

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?

like image 894
user1481096 Avatar asked Oct 01 '13 22:10

user1481096


People also ask

Is it possible to change functions context of execution?

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.

How do I add a property to an object?

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.

What is an execution context and how can we change it at runtime?

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.

How do you change the context of a given function in JavaScript?

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.


1 Answers

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.

like image 114
Bergi Avatar answered Oct 19 '22 12:10

Bergi