JavaScript with 为什么不推荐使用,其它语言如 Kotlin with 不是用得正酣吗

2023-01-10 04:06:12 +08:00
 nnegier

我查到的原因就两:一个是性能问题,另一个是严格模式报错。

但并不能解释我心中的疑问,要是不让用,造出来干嘛?而且简化代码不挺好的吗

3441 次点击
所在节点    程序员
18 条回复
netabare
2023-01-10 05:38:35 +08:00
因为 JavaScript 一开始就不是一个正经的语言。传说中的 10 天造出来的语言,能期待有多好的设计。

关于性能问题,我的猜测是,因为 JavaScript 是没有类型的,基于原型链的语言,这就意味着属性访问的实现方法和静态强类型 OOP 语言里面的 devirtualization 有很大的差别了。OOP 语言可以通过各种编译期的优化来消除 devirtualization 里面的性能开销,但是 JavaScript 的语言基准太灵活了,所以无法优化。(只是个人不负责任的猜想)

另外一个问题是`with`本身把变量直接引入到上下文里,也就是说,不需要写变量名就可以直接把关联在这个变量上的无论什么垃圾都调用出来。

Kotlin 里面的`with`并不会把变量关联的属性都暴露在上下文里,因为看函数签名就可以知道了:

```kotlin
inline fun <T, R> with(receiver: T, block: T.() -> R): R
```

receiver 是被捕获的变量,类型为 T ,block 是一个 receiver 函数,在这个函数里面,`this`的类型是 T ,也就是说必须显式指明`this`再访问这个变量所有可能的方法和属性。这种 aliasing 的写法,显然比把不管什么垃圾都倒进作用域安全多了。

话说过来在有 extension 的语言里,本身 scope 函数就可以自己随手造出来,当然了,scope 函数本身也涉及到了虚函数 devirtualization 的问题,如果语言运行时没有专门优化的话,是会造成性能问题的。

所以,并不是说「简化代码」就很好了。

至于「造出来的原因」,大概就跟语言设计历史上的各种其他的离谱的设计一样吧,因为当时的人们还没意识到哪些设计是好的,哪些是坏的。现在回过头看,也只是在马后炮了。
Mutoo
2023-01-10 05:58:30 +08:00
js 的 this 关键词已经够复杂了,with 可以把这个复杂性更进一层楼。猜一下输出:

```js
a = {this: 'this', that: 'that'};
with(a) { console.log(this, that); }
```
icoming
2023-01-10 07:17:27 +08:00
@Mutoo with 不会先从对象`a`里面找属性吗?
musi
2023-01-10 08:38:52 +08:00
首先你能查到的都是不推荐用,js 里面的糟粕又不止这一个,为啥非要揪着糟粕点
1t1y1ILnW0x5nt47
2023-01-10 08:53:17 +08:00
一不小心还容易污染全局
visper
2023-01-10 09:02:32 +08:00
vue 不是有用 with 吗?
TWorldIsNButThis
2023-01-10 09:04:13 +08:00
kotlin 的 with 只会拿到 public 的属性
js 呢?
MEIerer
2023-01-10 09:30:30 +08:00
设计简陋,导致不好用,所以 over
ToyotaLee
2023-01-10 09:36:06 +08:00
现在微前端框架不是用的很火,看使用场景
makelove
2023-01-10 09:43:03 +08:00
这个不推荐没有任何意义,正常人不会随便用 with ,毕竟没人会为了少打几个字而极大伤害可读性(毕竟看到每一个变量都得想具体会落到哪个对象上)。
要用到的地方不用都不行。
PTLin
2023-01-10 09:44:22 +08:00
我感觉 with 就是个顺势搞出来的东西。
本身 js 的作用域链进入一个新的作用域就推进去一个新的变量对象,那我估计设计 with 的是不是人是不是一拍脑子,想反正模型都是这样了,那直接出一个让用户把自己的对象推进作用域链头的东西不就好了。
NerbraskaGuy
2023-01-10 10:12:32 +08:00
JS 搞出来的操作符但是又不推荐用的多了去了,常见的比如 delete 的性能极差
cyrbuzz
2023-01-10 10:13:45 +08:00
只要可以了解副作用和承担副作用所带来的风险就可以用。

不推荐就是打了个标记,告诉开发者,你可以不用了解这个语法有啥卵用,我也不推荐让其他开发者学习这个语法,但你可以学习了解,并且在你觉得你完全了解它了,需要用它的时候用它。

比如 Vue 里有用`with`去实现模板的编译,`v-if="xxx === 2"`编译为`with(this) { if (xxx === 2) {...} }`,https://github.com/vuejs/petite-vue/blob/main/src/eval.ts#L20 petite-vue 里关于`with`的应用,这行代码很易读也并不会造成混乱(了解并承担了 with 会带来混乱作用域的副作用),实现了一个原本不用 with 会很复杂的功能。
cweijan
2023-01-10 10:31:25 +08:00
@NerbraskaGuy 这是取决于 V8 的实现吧, 而且前端也不缺这一点性能
thinkershare
2023-01-10 10:38:00 +08:00
SoloCompany
2023-01-10 13:30:02 +08:00
因为用了就只能依赖解释执行,无法 hotspot 优化
sundev
2023-01-10 13:57:28 +08:00
超级不喜欢 with 语法,看起来太费劲了
waiaan
2023-01-10 14:02:15 +08:00
@cyrbuzz
这种带变量的模板编译如果不用 with 的话还真想不到有啥好办法,用 with 就简单了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/907766

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX