Cheat morphology eval()

If the lexical scope is defined entirely by the location declared by the function during code writing, how can you modify (or cheat) the lexical scope at run time?

Lexical scope

What is lexical scope? When writing code, where variables and scopes are written is called lexical scoping, which remains the same as the lexical parser processes the code (mostly), and dynamic scoping, which is determined dynamically at run time. In dynamic scopes we do not care how functions and scopes are declared, only where they are called from.

There are two mechanisms in javaScript for this purpose (eval and with), but it’s not a good idea to use this mechanism in your code because cheating on lexicality can degrade performance.

The eval() function in JavaScript can take a string as an argument and treat its contents as if they existed in the scope at the time of writing. Here is an example of eval () :

function foo(str,b){ eval(str); console.log(a,b); //1 3 } var a=2; foo('var a=1; ', 3);Copy the code

In this code, foo() takes a string and a value as arguments. Foo passes STR to eval(), so the string “var a=1” is received as if it were already in the scope. So instead of calling var=2 when you want to print a, you’re going to look for a=1 in the body of the function because the body of the function is looking for variables from the inside out.

But it is not available in strict mode and has performance issues.

function foo(str,b){ "use strict" eval(str); console.log(a,b); //2 3 } var a=2; foo('var a=1; ', 3);Copy the code

In strict mode, eval() has its own scope, meaning that declarations in it cannot modify the current scope.

Cheat with()

With is often used as a shortcut to refer repeatedly to multiple properties of the same object without having to refer repeatedly to the object itself

var obj={
a:1
b:2
c:3
}
Copy the code

When we want to change a property to value 2, b property to value 3, and C property to value 4. The general approach is to use objects to access properties within objects one by one. See below:

obj.a=2;
obj.b=3;
obj.c=4;
Copy the code

However, we can quickly change the value of an object attribute by using with:

with(obj){
a=2;
b=3;
c=4;
}
Copy the code

But it’s really not just about easy access to object properties. Look at the code below

function foo(obj){ with(obj){ a=2; } } var o1={ a:3 } var o2={ b:3 } foo(o1); console.log(o1.a) //2 foo(o2); Log (o2.a) //undefined console.log(a) //2 a is leaked to the global scope! All codes are referenced in the book code!!Copy the code

In this case, two objects o1 and O2 are created, where O1 has an A attribute and O2 has no A attribute. foo(…) The function takes an obj argument. This argument is a reference to an object for which the with(obj){… }, inside with, what looks like a reference to variable A is actually an assignment to attribute A (reference to LHS: the purpose of the lookup is to assign a value to the variable), assigning 2 to a.

When executed on an O2 object, O2 does not have an a attribute, so this attribute is not created, and O2. a remains undefined.

With can treat an object with no or multiple attributes as a fully isolated lexical scope, so the attributes of the object are also treated with lexical identifiers defined in the song scope.

But in the O2 scope, foo (…) The a identifier was not found in either the scope or the global scope, so when a=2, a global variable was created.