with
前面我们学习了作用域和作用域链,当一个函数中的变量需要使用时首先会在自己的AO中进行查找,如果没有它将会沿着作用域链向上查找,直到找到全局的GO为止。
const message = 'hello world'
function foo() {
function bar() {
console.log(message)
}
bar()
}
foo()
此时控制台会打印出hello world字符串,bar函数在自己的AO中没有找到message就往foo函数中查找,foo函数中没有就往全局查找,最终打印出字符串。而今天要说的with和这个有什么关系呢?
const message = 'hello world'
const obj = {
message: 'zengge'
}
function foo() {
function bar() {
with(obj) {
console.log(message)
}
}
bar()
}
foo()
我们将开头的代码修改了一下,使用with语句进行包裹,可以猜想此时message打印出来什么?没错就是zengge。看到这里你应该知道with语句的作用是什么了。with语句的作用就是修改当前的作用域,使得with语句花括号内的变量首先往obj内进行查找,然后再沿着作用域链进行查找。但是我们却并不推荐使用with在开发中,原因有以下几点:
with语句使得程序在查找变量值时,都是先在指定的对象中查找。所以那些本来不是这个对象中的属性的变量查找起来会很慢。如果对性能要求较高的场合,with下面的statement语句中的变量,只应该包含这个指定对象的属性。- 从代码读写(语义)角度来考虑,
with语句打散了对象与属性的关联性(书写和阅读),不利于代码的阅读。 - 从兼容性角度来考虑,
with不能在严格模式下使用;而且还无法向前兼容,而ES6更是有一些语法可以替代with一些功能,比如let可以绑定作用域来替代with生成的作用域等。
eval
eval是一个特殊的函数,它可以将传入的字符串当成Javascript代码来执行。
eval('console.log("hello world")')
但是开发中我们也不推荐使用eval函数,原因有两点:
- 效率较低,需要由
js解释器转为字节码然后转为机器码最后才能识别。 - 不安全,由于
eval中的操作数据可能是由后台传过来的字符串,不法分子很容易就可以截取到这些字符并且可以任意修改,导致程序的瘫痪。 - 可读性以及维护性差。
严格模式
严格模式(Strict Mode)是在es5中提出来的概念。设置严格模式主要有几个目的:
- 消除
Javascript语法的一些不合理、不严谨之处,减少一些怪异行为 - 消除代码运行的一些不安全之处,保证代码运行的安全
- 提高编译器效率,增加运行速度
- 为未来新版本的
Javascript做好铺垫 以下的代码在非严格模式可以正常运行,但是在严格模式下都是报错的,列举了部分的代码:
"use strict"
const obj = {
name: 'zengge'
}
message = 'zenggda' // 报错,没有使用关键字定义变量
Object.freeze(obj) // 冻结对象
obj.name="lisi" // 报错,静默错误
function(x, y, x) { // 报错,重复定义参数名称
console.log(x, y, x)
}
const num = 0o123 // 报错,不允许使用八进制格式
with(obj){ // 报错,不允许使用with
console.log(name)
}
...