4

精读《JS with 语法》

 3 years ago
source link: https://zhuanlan.zhihu.com/p/397800013
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

精读《JS with 语法》

前端开发话题下的优秀答主

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 的用法是前端模版引擎。

我们经常看到模版引擎里会有一些 forEachmap 等特殊用法,这些语法完全可以通过 with 注入。当然并不是所有模版引擎都是这么实现的,还有另一种方案是,现将模版引擎解析为 AST,再根据 AST 构造并执行,如果把这个过程放到编译时,那么 JSX 就是一个例子。

最后关于 with 注入上下文,还有一个误区,那就是认为下面的代码仅仅注入了 run 属性:

with ({ run: () => {} }) {
  run()
}

其实不然,因为 with 会在整个原型链上查找,而 {} 的原型链是 Object.prototype,这就导致挂在了许多非预期的属性。

如果想要挂载一个纯净的对象,可以使用 Object.create() 创建对象挂载到 with 上。

总结

with 的使用场景很少,一般情况下不推荐使用。

如果你还有其他正经的 with 使用场景,可以告知我,或者给出评论。

讨论地址是:精读《JS with 语法》· Issue #343 · dt-fe/weekly

如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

关注 前端精读微信公众号

v2-d46b608443dd2afa3dea21b96236fa06_720w.jpg

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK