当前位置: 首页 > Web前端 > JavaScript

精读《JS with 语法》

时间:2023-03-27 01:42:55 JavaScript

with是一种不推荐的语法,因为它的作用是改变上下文,而上下文环境对开发者的影响很大。在本周的JavaScript之ForgottenKeyword(with)一文中,我将介绍with的作用。概述下面是一个使用with的例子:with(console){log('我不再需要“console.”部分了!');}我们将console对象注入到上下文中,并注册了console.log属性在这个范围内。另一个例子:with(console){with(['a','b','c']){log(join(''));//将“abc”写入控制台。通过嵌套,我们可以追加注入的上下文。其中with(['a','b','c'])实际上是将['a','b','c']的返回值对象注入到上下文中,数组对象有一个.join成员函数,所以可以直接调用join('')输出"abc"。为了不让结果如此神奇,建议通过枚举声明要注入的key:with({myProperty:'Helloworld!'}){console.log(myProperty);//Logs"Helloworld!"}那么为什么不推荐使用with呢?例如下面的情况:functiongetAverage(min,max){with(Math){returnround((min+max)/2);}}getAverage(1,5);注入的上下文可能与现有上下文冲突,导致输出NaN。所以不建议在业务代码中使用with,其实with在严格模式下也是被禁用的。精读由于with定义的context会被优先搜索,是前端沙箱领域的解决方案。具体方法是:constsandboxCode=`with(scope){${code}}`newFunction('scope',sandboxCode)这样就限制了scope定义的所有对象。但是如果访问范围外的对象还是会冒泡搜索,我们可以结合Proxy来限制搜索范围,这样就可以完成一个可用性可以接受的沙盒。with的第二个用法是前端模板引擎。我们经常在模板引擎中看到一些特殊的用法比如forEach、map,这些语法都可以通过with注入。当然,并不是所有的模板引擎都是这样实现的。另一种方案是将模板引擎解析成AST,然后根据AST构造并执行。如果把这个过程放到编译中,那么JSX就是一个例子。最后,对于with注入的上下文还有一个误解,就是下面的代码只注入了run属性:with({run:()=>{}}){run()}其实不是这样的,因为with会在整个原型链中查找,而{}的原型链是Object.prototype,导致挂在很多意想不到的属性上。如果你想挂载一个纯对象,你可以使用Object.create()创建一个对象并挂载它。总结with的使用场景很少,一般不推荐使用。如果你有其他严重的使用场景,你可以让我知道,或者发表评论。讨论地址为:Jingdu《JS with 语法》·Issue#343·dt-fe/weekly想参与讨论的请戳这里,每周都有新话题,周末或周一发布。前端精读——帮你过滤靠谱的内容。关注前端精读微信公众号版权声明:免费转载-非商业-非衍生保留属性(CreativeCommons3.0License)