with 是一个不举荐应用的语法,因为它的作用是扭转上下文,而上下文环境对开发者影响很大。
本周通过 JavaScript’s Forgotten Keyword (with) 这篇文章介绍一下 with 的性能。
概述
上面是一种应用 with 的例子:
with (console) {log('I dont need the"console."part anymore!');
}
咱们往上下文注入了 console
对象,而 console.log
这个属性就被注册到了这个 Scope 里。
再比方:
with (console) {with (['a', 'b', 'c']) {log(join('')); // writes"abc" to the console.
}
}
通过嵌套,咱们能够追加注入上下文。其中 with (['a', 'b', 'c'])
其实是把 ['a', 'b', 'c']
的返回值对象注入到了上下文,而数组对象具备 .join
成员函数,所以能够间接调用 join('')
输入 "abc"
。
为了不让后果这么 Magic,倡议以枚举形式申明要注入的 key:
with ({myProperty: 'Hello world!'}) {console.log(myProperty); // Logs "Hello world!"
}
那为什么不举荐应用 with 呢?比方上面的状况:
function getAverage(min, max) {with (Math) {return round((min + max) / 2);
}
}
getAverage(1, 5);
注入的上下文可能与已有上下文产生抵触,导致输入后果为 NaN
。
所以业务代码中不举荐应用 with,而且实际上在 严格模式 下 with 也是被禁用的。
精读
因为 with 定义的上下文会优先查找,因而在前端沙盒畛域是一种解决方案,具体做法是:
const sandboxCode = `with(scope) {${code} }`
new Function('scope', sandboxCode)
这样就把所有 scope 定义的对象限定住了。但如果拜访 scope 外的对象还是会向上冒泡查找,咱们能够联合 Proxy 来限度查找范畴,这样就能实现一个可用性尚可的沙盒。
第二种 with 的用法是前端模版引擎。
咱们常常看到模版引擎里会有一些 forEach
、map
等非凡用法,这些语法齐全能够通过 with 注入。当然并不是所有模版引擎都是这么实现的,还有另一种计划是,现将模版引擎解析为 AST,再依据 AST 结构并执行,如果把这个过程放到编译时,那么 JSX 就是一个例子。
最初对于 with 注入上下文,还有一个误区,那就是认为上面的代码仅仅注入了 run
属性:
with ({run: () => {}}) {run()
}
其实不然,因为 with 会在整个原型链上查找,而 {}
的原型链是 Object.prototype
,这就导致挂在了许多非预期的属性。
如果想要挂载一个污浊的对象,能够应用 Object.create()
创建对象挂载到 with 上。
总结
with 的应用场景很少,个别状况下不举荐应用。
如果你还有其余正经的 with 应用场景,能够告知我,或者给出评论。
探讨地址是:精读《JS with 语法》· Issue #343 · dt-fe/weekly
如果你想参加探讨,请 点击这里,每周都有新的主题,周末或周一公布。前端精读 – 帮你筛选靠谱的内容。
关注 前端精读微信公众号
<img width=200 src=”https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg”>
版权申明:自在转载 - 非商用 - 非衍生 - 放弃署名(创意共享 3.0 许可证)