javascript 是否可以将块的结果赋给变量?

ee7vknir  于 2023-10-14  发布在  Java
关注(0)|答案(4)|浏览(97)

像这样的代码块在Chrome控制台和repl中产生一个值

{
  let x = 1;
  for (let i = 1; i < 10; i += 1) {
    x *= i;
  }
  x;
}

是否可以将块的结果赋给变量?
这将抛出一个错误,因为{}在这里被解释为对象

const a = {
  let x = 1;
  for (let i = 1; i < 10; i += 1) {
    x *= i;
  }
  x;
}
m3eecexj

m3eecexj1#

JavaScript不像其他语言那样有块表达式。正如你所注意到的,它变成了一个对象/错误。
你可以做的是使用一个IIFE并从它返回一个值。

const a = (() => {
  let x = 1;
  for (let i = 1; i < 10; i += 1) {
    x *= i;
  }
  return x;
})();

console.log(a)

由于constlet具有比var更健壮的作用域规则,因此块的点数大大增加。它也将与新的using支持有用。

bybem2ql

bybem2ql2#

你必须写一个函数,或者类似的东西。

const fn = () => {
  let x = 1;
  for (let i = 1; i < 10; i += 1) {
    x *= i;
  }
  return x;
}

const a = fn();
1u4esq0p

1u4esq0p3#

它似乎像eval工程(我知道eval是邪恶的)

const a = eval(`{
  let x = 1;
  for (let i = 1; i < 10; i += 1) {
    x *= i;
  }
  x;
}`)

console.log(a)
neekobn8

neekobn84#

我想任何人都可以享受这个简单的call功能。你可以把它重命名为block,如果它能帮助你用这些术语思考的话-

const call = (f, ...args) => f(...args)

console.log(call(() => {
  let x = 1;
  for (let i = 1; i <= 10; i += 1) {
    x *= i;
  }
  return(x);
}))

console.log(call(
  function recur(x) {
    return x == 0 ? 1 : x * recur(x - 1)
  },
  10
))

console.log(call(
  function recur(x, prod) {
    return x == 0 ? prod : recur(x - 1, prod * x)
  },
  10,
  1
))

当使用call和递归函数时,如果可以提前确定结果,我们通常需要一种退出函数的方法。call函数可以与callcccall with current continuation组合,最初在this Q&A中演示。

const call = (f, ...args) => f(...args)

const callcc = f => {
  const box = Symbol()
  try { return f(unbox => { throw {box, unbox} }) }
  catch (e) { if (e?.box == box) return e.unbox; throw e  }
}

const product = numbers =>
  callcc(exit => call(function recur(x) {
    if (x.length == 0) return 1
    if (x[0] == 0) exit(0) // immediate exit
    return x[0] * recur(x.slice(1))
  }, numbers))

console.log(product([1,2,3,4,5,6,7,8,9,10])) // 3628800
console.log(product([1,2,3,4,5,0,7,8,9,10])) // 0
  
const find = (tree, query) =>
  callcc(exit => call(function recur(t) {
    if (t == null) return
    if (t[0] == query) exit(t) // immediate exit!
    for (const child of t[1] ?? []) recur(child)
  }, tree))
  
const mytree =
  [0, [[1], [2, [[3], [4, [[5]]]]]]]
  
console.log(JSON.stringify(find(mytree, 3))) // [3]
console.log(JSON.stringify(find(mytree, 4))) // [4,[[5]]]
console.log(JSON.stringify(find(mytree, 9))) // undefined

这两个函数都可以是类型安全的-

function call<R>(f: () => R): R
function call<A, R>(f: (a: A) => R, a: A): R
function call<A, B, R>(f: (a: A, b: B) => R, a: A, b: B): R
function call<A, B, C, R>(f: (a: A, b: B, c: C) => R, a: A, b: B, c: C): R
function call<A, B, C, D, R>(f: (a: A, b: B, c: C, d: D) => R, a: A, b: B, c: C, d: D): R
function call<A, B, C, D, E, R>(f: (a: A, b: B, c: C, d: D, e: E) => R, a: A, b: B, c: C, d: D, e: E): R
function call<R>(f: (...args: unknown[]) => R, ...args: unknown[]): R {
  return f(...args) as R
}
function callcc<R>(f: (exit: (value: R) => R) => R): R {
  class Box { public unbox: R; constructor(v: R) { this.unbox = v  } }
  try { return f(value => { throw new Box(value) }) }
  catch (e) { if (e instanceof Box) return e.unbox; throw e  }
}

相关问题