Detailed explanation of the rejected eval function and with statement examples in JavaScript learning summary

  • 2021-07-06 10:09:47
  • OfStack

Previous words

eval and with are often rejected as if their existence is a mistake. In CSS, tables are rejected, and only tables are used to display data in web pages instead of layout, which may be dismissed as irregular and overkill. What exactly is the situation about eval and with? This article describes the eval () function and the with statement in detail

eval

Definition

eval () is a global function, and javascript uses eval () to interpret and run strings composed of javascript source code


var result = eval('3+2');
console.log(result,typeof result);//5 'number' 

Usage

eval () has only one parameter, and if the parameter passed in is not a string, it returns this parameter directly. If the parameter is a string, it compiles the string as javascript code. If compilation fails, a syntax error (syntaxError) exception is thrown. If the compilation is successful, the code is executed and the value of the last expression or statement in the string is returned. If the last expression or statement has no value, undefined is finally returned. If the string throws an exception, the exception passes the call to eval ()


var num = 1;
var str = 'test';
console.log(eval(num));//1
console.log(eval(str));//ReferenceError: test is not defined 
var strLong1 = 'var x = 1;var y = 2;';
console.log(eval(strLong1),x,y);//undefined 1 2
var strLong2 = 'var x = 1; x++;';
console.log(eval(strLong2),x);//1 2 

Scope

eval () uses the variable-scoped environment in which it was called. That is, it finds the value of the variable and defines the operation of the new variable and function and the code in the local scope completely 1 sample


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

Alias

When called by alias, eval () executes its string as top-level global code. Code that executes may define new global variables and global functions, or assign values to global variables, but cannot use or modify local variables in functions


var geval = eval; 
var x = 'global',y = 'global'; 
function f(){
var x = 'local';
eval('x += "changed";');
return x;
}
function g(){
var y = 'local';
geval('y += "changed";');
return y;
}
console.log(f(),x);//localchanged global
console.log(g(),y);//local globalchanged 

[Note] IE8-Browser calls to eval () by alias have the same result as normal calls to eval ()

Side effects

The javascript interpreter does a lot of code analysis and optimization. The problem with eval () is that the code used for dynamic execution is usually not parsed, and therefore the interpreter cannot optimize it, which leads to performance degradation

Similar to eval () are setTimeout (), setInterval (), new Function (), etc. These functions can be dynamically executed while the program is running, taking strings as parameters. The benefits of this execution mechanism cannot offset its performance loss, so it should be avoided as much as possible

Strict model

Because the eval () function is too powerful, strict schema restricts it strictly

'1' cannot create a variable or function through the eval () function, but its value can be queried and changed


'use strict';
eval('var x = 1;');
console.log(x);//ReferenceError: x is not defined
'use strict';
var x = 1;
eval('x = 2;');
console.log(x);//2 

'2' Prohibits eval as an identifier


'use strict';
var eval = 10;//SyntaxError: Unexpected eval or arguments in strict mode 

with

The main purpose of defining the with statement is to simplify the work of writing the same 1 object multiple times

The with statement adds object to the header of the scope chain, then executes statement, and finally restores the scope chain to its original state


with(object){
    statement;
}

Action

The with statement is often used to simplify code writing when objects are deeply nested. In essence, a new lexical scope is created by treating the reference of an object as a scope and the attribute of an object as an identifier in the scope

In the client javascript, an expression like the following may be used to access an element in an HTML form


document.forms[0].address.value 

If this expression occurs multiple times in your code, you can use the with statement to add an form object to the top level of the scope chain


with(document.forms[0]){
name.value = '';
address.value = '';
emai.value = '';
} 

This method reduces a lot of input and eliminates the need to prefix each attribute name with document. forms [0]. This object is temporarily mounted on the scope chain, and is automatically found in this object when javascript needs to resolve identifiers such as address

[Note] The with statement provides a shortcut to read an object's properties, but it does not create an object's properties

If the object o has one attribute x, the following code assigns this attribute a value of 1


var o = {x:0};
with(o) x = 1;
console.log(o.x);//1 

If the attribute x is not defined in o, the following code and the code x=1, which does not use the with statement, are identical. This is because the variable x is queried for LHS and 1 is assigned to it


var num = 1;
var str = 'test';
console.log(eval(num));//1
console.log(eval(str));//ReferenceError: test is not defined 
var strLong1 = 'var x = 1;var y = 2;';
console.log(eval(strLong1),x,y);//undefined 1 2
var strLong2 = 'var x = 1; x++;';
console.log(eval(strLong2),x);//1 2 
0

Side effects

Like eval, the javascript code for the with statement is very difficult to optimize and debug, and it is slower than the code without the with statement

Moreover, if the with statement is improper, it may cause variable leakage and pollute the global scope


var num = 1;
var str = 'test';
console.log(eval(num));//1
console.log(eval(str));//ReferenceError: test is not defined 
var strLong1 = 'var x = 1;var y = 2;';
console.log(eval(strLong1),x,y);//undefined 1 2
var strLong2 = 'var x = 1; x++;';
console.log(eval(strLong2),x);//1 2 
1

Strict model

In strict mode, the use of with statements is prohibited


var num = 1;
var str = 'test';
console.log(eval(num));//1
console.log(eval(str));//ReferenceError: test is not defined 
var strLong1 = 'var x = 1;var y = 2;';
console.log(eval(strLong1),x,y);//undefined 1 2
var strLong2 = 'var x = 1; x++;';
console.log(eval(strLong2),x);//1 2 
2

Finally

Using eval and with prevents the engine from optimizing scope lookup at compile time, resulting in performance degradation and slow code running. Because eval and with are rarely used in practical work, the restrictions in strict mode have little impact on us. Just like, for example, the Ministry of Foreign Affairs announced one day that China will no longer issue visas to Jamaica. Although Jamaica has heard of it, most people may not go once in their lives, so it doesn't matter. Similarly, it doesn't matter if eval and with are rejected or not


Related articles: