V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nnegier
V2EX  ›  程序员

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

  •  
  •   nnegier · 2023-01-10 04:06:12 +08:00 · 3397 次点击
    这是一个创建于 676 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    18 条回复    2023-01-10 14:02:15 +08:00
    netabare
        1
    netabare  
       2023-01-10 05:38:35 +08:00   ❤️ 1
    因为 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
        2
    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
        3
    icoming  
       2023-01-10 07:17:27 +08:00
    @Mutoo with 不会先从对象`a`里面找属性吗?
    musi
        4
    musi  
       2023-01-10 08:38:52 +08:00
    首先你能查到的都是不推荐用,js 里面的糟粕又不止这一个,为啥非要揪着糟粕点
    1t1y1ILnW0x5nt47
        5
    1t1y1ILnW0x5nt47  
       2023-01-10 08:53:17 +08:00
    一不小心还容易污染全局
    visper
        6
    visper  
       2023-01-10 09:02:32 +08:00
    vue 不是有用 with 吗?
    TWorldIsNButThis
        7
    TWorldIsNButThis  
       2023-01-10 09:04:13 +08:00 via iPhone
    kotlin 的 with 只会拿到 public 的属性
    js 呢?
    MEIerer
        8
    MEIerer  
       2023-01-10 09:30:30 +08:00
    设计简陋,导致不好用,所以 over
    ToyotaLee
        9
    ToyotaLee  
       2023-01-10 09:36:06 +08:00
    现在微前端框架不是用的很火,看使用场景
    makelove
        10
    makelove  
       2023-01-10 09:43:03 +08:00
    这个不推荐没有任何意义,正常人不会随便用 with ,毕竟没人会为了少打几个字而极大伤害可读性(毕竟看到每一个变量都得想具体会落到哪个对象上)。
    要用到的地方不用都不行。
    PTLin
        11
    PTLin  
       2023-01-10 09:44:22 +08:00
    我感觉 with 就是个顺势搞出来的东西。
    本身 js 的作用域链进入一个新的作用域就推进去一个新的变量对象,那我估计设计 with 的是不是人是不是一拍脑子,想反正模型都是这样了,那直接出一个让用户把自己的对象推进作用域链头的东西不就好了。
    NerbraskaGuy
        12
    NerbraskaGuy  
       2023-01-10 10:12:32 +08:00
    JS 搞出来的操作符但是又不推荐用的多了去了,常见的比如 delete 的性能极差
    cyrbuzz
        13
    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
        14
    cweijan  
       2023-01-10 10:31:25 +08:00
    @NerbraskaGuy 这是取决于 V8 的实现吧, 而且前端也不缺这一点性能
    thinkershare
        15
    thinkershare  
       2023-01-10 10:38:00 +08:00
    SoloCompany
        16
    SoloCompany  
       2023-01-10 13:30:02 +08:00 via iPhone
    因为用了就只能依赖解释执行,无法 hotspot 优化
    sundev
        17
    sundev  
       2023-01-10 13:57:28 +08:00 via iPhone
    超级不喜欢 with 语法,看起来太费劲了
    waiaan
        18
    waiaan  
       2023-01-10 14:02:15 +08:00
    @cyrbuzz
    这种带变量的模板编译如果不用 with 的话还真想不到有啥好办法,用 with 就简单了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1418 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 17:48 · PVG 01:48 · LAX 09:48 · JFK 12:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.