JavaScript系列:认识JS中的with、eval和严格模式

150 阅读3分钟

JavaScript中的一些小知识点,需要了解。

with语句

with语句:扩展一个语句的作用域链。(不推荐使用)

 // 简单的代码
 var message = "copyer";
 function foo() {
   console.log(message);
 }
 foo();

查找message的作用域链:

07_1.png

 // with语句
 var message = "copyer";
 var withObj = { message: "with语句中的message" };
 function foo() {
   with (withObj) {
     console.log(message); // with语句中的message
   }
 }
 foo();

查找message的作用域链

07_2.png 这里就是在作用域链加上了一个with的作用域,如果找到了message就停止寻找。

具体使用

with语句 跟 if语句形式是差不多的,都是后面跟上一个小括号。

  • if 括号里面存放条件
  • with 括号里面存放一个变量,在with的作用域中,就存放该变量。

eval函数

eval是一个特殊的函数,它可以将传入的字符串当做JavaScript代码执行。(不推荐使用)

 const str = 'var message = "copyer"; console.log(message);'
 eval(str) // copyer
 console.log(message) // copyer

eval解析字符串成JavaScript代码,也就相当于普通的代码执行,所以在外面也能访问里面的变量。

后面学习到的知识

(function() {
  (0,eval)("var foo = 123"); // indirect call to eval, creates global variable
})();
console.log(foo);            // 123
(function() {
  eval("var bar = 123");     // direct call to eval, creates local variable
})();
console.log(bar);            // ReferenceError

stackoverflow.com/questions/4…

不推荐使用的原因:

  • eval的代码可读性非常差(代码的可读性是高质量代码的重要原则)。
  • eval执行必须经过JS的解释器,不能被JS引擎优化。

严格模式

在ECMAScript5中,JavaScript提出严格模式的概念(Strict Moda)。

JavaScript的语法过于灵活,严格模式就是用来限制JavaScript过于灵活的写法。

 message = 'copyer' // 没有使用关键词 var 来定义变量,以致于message保存在window上(变量污染)
 ​
 true.name = 'copyer' // 毫无意义的写法,但是也不会保错
 ​
 var obj = {};
 Object.defineProperty(obj, "message", {
   writable: false,  // 给对象对象添加不可编辑的特性
   value: "copyer",
 });
 console.log(obj.message); 
 obj.message = 'kobe'  // 也可直接编辑,没有报错(虽然也没有修改成功)

还有很多的(无意义)的写法,JavaScript都不会报语法错误。

所以严格模式就产生了,需要限制一下,直接报语法错误等信息。

支持严格模式的浏览器在检测代码中有严格模式时,会以更加严格的方式对代码进行检测和执行

严格模式对正常的JavaScript语法进行一些限制:

  • 严格模式通过抛出错误来抛出一些语法错误
  • 严格模式让JS引擎在执行代码时进行更多的优化(不需要对一些特殊的语法进行处理)

开启严格模式的方式:

  • 针对整个JS文件:在js文件的第一行:use strict
  • 针对某个函数:在函数体内的第一行:use strict

严格模式的限制

1、无法意外的创建全局变量

 "use strict";
 message = 'copyer'
 // 报错: Uncaught ReferenceError: message is not defined

2、对无意义的写法,抛出异常

 "use strict";
 true.name = 'copyer'
 // 报错:Uncaught TypeError: Cannot create property 'name' on boolean 'true'

3、对不可编辑的属性进行修改(或则删除)

 "use strict";
 var obj = {};
 Object.defineProperty(obj, "message", {
   writable: false,  // 给对象对象添加不可编辑的特性
   value: "copyer",
 });
 obj.message = 'kobe'  
 // 报错:buchong.js:7 Uncaught TypeError: Cannot assign to read only property 'message' of object '#<Object>'

4、不允许函数参数具有相同的名称

 "use strict";
 function foo(a,b,a) {
     // a: 30
 }
 foo(10,20,30)
 // 报错:Uncaught SyntaxError: Duplicate parameter name not allowed in this context

5、严格模式下,不能使用with语句

6、eval函数不在为上层引用变量

 "use strict";
 const str = 'var message = "copyer"; console.log(message);'
 eval(str) // copyer
 console.log(message) // Uncaught ReferenceError: message is not defined

7、this的指向: 默认绑定的this为undefined

 "use strict";
 foo() {
   console.log(this) // undefined
 }
 foo()
 ​
 setTimeout(() => {
   console.log(this) // 箭头函数:window
 }, 10)
 ​
 setTimeout(function () {
   console.log(this) // 普通函数: window
 }, 10)

\