生成 DOM 元素时替代 JavaScript `with` 语句

问题描述 投票:0回答:4

假设我有一个 JavaScript 库来生成如下所示的 DOM 片段

<main>
  <h1>A heading</h1>
  <p>A paragraph</p>
</main>

其中库

domlib
具有适用于任何类型元素的方法,并且生成上面片段的函数可能如下所示:

function(domlib){
  return domlib.main(
    domlib.h1('A heading'),
    domlib.p('A paragraph')
  );
}

在这个函数中,我宁愿调用这样的

domlib
方法:

main(
  h1('A heading'),
  p('A paragraph')
)

为了实现这一点,我可以将

domlib
的所有方法放在全局范围内,但我宁愿避免污染全局范围。对我来说,这似乎是
with
语句是理想解决方案的情况:

function(domlib){
  with(domlib){
    return main(
      h1('A heading'),
      p('A paragraph')
    );
  }
}

虽然仍然受支持,但

with
语句实际上已被弃用,并且会在严格模式下抛出错误

除了将

domlib
方法分配给局部函数变量之外,我没有看到很多其他选项,但这很容易导致分配数十个局部变量,在这种情况下,第一种方法(直接调用
domlib
上的方法)将导致更简单的代码。

我的问题是,有没有其他替代方案可以实现我想要的,并且具有与使用

with
语句类似的简单性和可读性?

javascript scope with-statement
4个回答
10
投票

我将使用的方法是通过解构显式列出我想要的元素。

例如,在你的情况下,我会有这样的东西:

const component = ({main, h1, p}) => main(
  h1('A heading'),
  p('A paragraph')
);

这与做类似

const component = (domlib) => {
  const {main, h1, p} = domlib;
  return main(
    h1('A heading'),
    p('A paragraph')
  );
};

2
投票

你可以使用 es6 轻松实现这一点 :

const functionName = ({ main, h1, p }) => main(h1('heading'), p('paragraph'))

functionName(domlib)

但是跨浏览器会遇到困难,因为 es6 不完全支持


2
投票

另一种选择是重新设计

domlib
,以便它以类似于

的方式支持链接
domlib
    .begin('main')
        .h1('A heading')
        .p('A paragraph')
    .end()

...但在现实生活中的代码中,我宁愿将

domlib
替换为
$
_
:

function($){
    return $.main(
       $.h1('A heading'),
       $.p('A paragraph')
    );
}

每次调用两个额外字符的开销是避免欺骗和黑客行为的合理价格。


0
投票

我对这个主题的 2 美分(KaboomJS/KaPlay 也有类似的问题,我想将其从 replit 移植到 vue 应用程序以供实习生使用)

let htmlFragment = (function() {
  return main(
    h1('A heading'),
    p('A paragraph')
  );
}).apply(domLib); // executes function with specific context

作为

with(domLib){}

的替代品

替代方案:

let func = (function() { return main(...); }).bind(domLib); // bind context for later use

let htmlFragment = func();
© www.soinside.com 2019 - 2024. All rights reserved.