发布于 2026-01-06 0 阅读
0

JavaScript:精​​彩部分

JavaScript:精​​彩部分

JavaScript 发展迅猛,每年都会新增大量功能。其中一些功能从未引起关注,另一些则被遗忘或弃用。让我们把这些功能放到越来越复杂、可编辑的代码沙箱中。我们的目标是让你在体验过程中时不时地体验到惊险刺激。

这些示例均取自多年来我编写的真实库或应用程序。不过,最后几个示例颇具争议,我不建议您在代码中使用它们。

最后

我通常在需要给其他开发者的函数添加一些额外逻辑时使用finallyfinally 。这样做不会改变函数的原始行为,例如返回值或抛出的错误。

此示例通过性能测量为传递的函数添加指标。

function measure (fn) {
  const start = Date.now()
  try {
    return fn()
  } finally {
    console.log(`${fn.name} took ${Date.now() - start} ms`)
  }
}
Enter fullscreen mode Exit fullscreen mode

编辑 l9wj5zx20l

WeakSet 和 WeakMap

这两个属性提供的是真正私有的属性(与Symbol不同)。我通常在需要向他人对象添加一些元数据时使用它们。直接修改这些属性是不礼貌的,而且如果对象被冻结,那就麻烦了。

此示例将传入的对象字符串化并缓存结果。记忆化操作加快了运算速度,而使用 Wea​​kMap 则避免了对象污染和内存泄漏。

const cache = new WeakMap()

export default function stringify(obj) {
  let result = cache.get(obj)
  if (!result) {
    result = JSON.stringify(obj, null, 2)
    cache.set(obj, result)
  }
  return result
}
Enter fullscreen mode Exit fullscreen mode

编辑 wn1ror8jz5

代理人

代理可以调整语言的行为。大多数情况下,我用它们来扩展语言的功能,偶尔也会用它们来彻底改变一些默认行为。

这个响应式示例允许你创建可观察对象和反应。当反应中使用的可观察对象发生变更时,反应会自动重新运行。这段代码非常简化,但稍加修改就能实现更多功能。

let runningFn
const reactions = new WeakMap()

export function observe(fn) {
  runningFn = fn
  try {
    return fn()
  } finally {
    runningFn = undefined
  }
}

export function observable(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      runningFn && reactions.set(target, runningFn)
      return Reflect.get(target, key, receiver)
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver)
      const reaction = reactions.get(target)
      reaction && reaction()
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

编辑 wn7nz5x7x8

新功能

`new Function()` 与 `new Function()`类似,eval但它会在全局作用域中创建函数,而全局作用域不受任何'strict mode'声明的限制。我们很快就会利用这一点。

这个例子可以获取global对象——无论平台如何——这目前比预期的要复杂一些。它也被用于ES2019 globalThis 提案的polyfill 中。

const globalThis = new Function('return this')()
Enter fullscreen mode Exit fullscreen mode

如果你的页面设置了内容安全策略 (CSP),那么这种方法行不通。

`with`会扩展语句的作用域链。可惜的是,它已被弃用,并且在严格模式下(包括 ES6 模块)无法正常工作。不过,一些技巧可以解决这个问题。

这个例子允许你编写类似 Vue 或 Angular 的模板文件,并在传递的状态上下文中渲染它们。

export default function compile(template) {
  return new Function("state", `with (wrap(state)) { return \`${template}\` }`)
}

window.wrap = state => new Proxy(state, {
  has: () => true
})
Enter fullscreen mode Exit fullscreen mode

编辑 wyv631ry7k

with通过以下技巧来调整行为:

  • 它使用new Function()`-` 而不是eval`-` 来创建全局作用域中的函数。全局作用域位于严格模式之外,因此with可以正常工作。

  • with它使用代理来稍微调整行为。通常情况下,with它会扩展作用域链,而不是完全替换它。当在传入的对象上找不到某个属性时,它会在下一个作用域(在本例中是全局作用域)中查找。我们不希望全局作用域泄露到模板中,因此我们必须欺骗模板,让它认为传入的对象上存在所有可能的属性。使用代理陷阱with可以轻松实现这一点has

一切归于一体

我们在开发过程中意外地创建了一个速度极快、轻量级的 MVC 框架。

点击此处查看代码库,别忘了点个赞哦!


希望你抽出时间玩了玩沙盒游戏。如果你创作出了什么奇思妙想,请留言分享。

感谢阅读!

文章来源:https://dev.to/solkimicreb/javascript-the-fun-parts-15cb