Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么赢了';是否在“.map”回调中不产生返回?_Javascript_Node.js_Generator_Ecmascript 6 - Fatal编程技术网

Javascript 为什么赢了';是否在“.map”回调中不产生返回?

Javascript 为什么赢了';是否在“.map”回调中不产生返回?,javascript,node.js,generator,ecmascript-6,Javascript,Node.js,Generator,Ecmascript 6,该解决方案使用了一个for循环,但我在回调中找不到任何涉及收益率的内容 我猜答案是:不要那样做,但如果有人有时间或意愿提供解释,请提前感谢 代码: function *upper (items) { items.map(function (item) { try { yield item.toUpperCase() } catch (e) { yield 'null' } } } var badItems = ['a', 'B', 1,

该解决方案使用了一个
for循环
,但我在回调中找不到任何涉及收益率的内容

我猜答案是:
不要那样做
,但如果有人有时间或意愿提供解释,请提前感谢

代码:

function *upper (items) {
  items.map(function (item) {
    try {
      yield item.toUpperCase()
    } catch (e) {
      yield 'null'
    }
  }
}

var badItems = ['a', 'B', 1, 'c']

for (var item of upper(badItems)) {
  console.log(item)
}
// want to log: A, B, null, C
⇒  learn-generators run catch-error-map.js
/Users/gyaresu/programming/projects/nodeschool/learn-generators/catch-error-map.js:4
      yield item.toUpperCase() // error below
            ^^^^
SyntaxError: Unexpected identifier
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3
错误:

function *upper (items) {
  items.map(function (item) {
    try {
      yield item.toUpperCase()
    } catch (e) {
      yield 'null'
    }
  }
}

var badItems = ['a', 'B', 1, 'c']

for (var item of upper(badItems)) {
  console.log(item)
}
// want to log: A, B, null, C
⇒  learn-generators run catch-error-map.js
/Users/gyaresu/programming/projects/nodeschool/learn-generators/catch-error-map.js:4
      yield item.toUpperCase() // error below
            ^^^^
SyntaxError: Unexpected identifier
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3
就连我的编辑都知道这是个糟糕的主意……


一个问题是
yield
只向函数的调用者提供一个级别。因此,当您在回调中
产生
时,它可能不会做您认为它会做的事情:

// The following yield:
function *upper (items) { // <---- does not yield here
  items.map(function (item) { // <----- instead it yields here
    try {
      yield item.toUpperCase()
    } catch (e) {
      yield 'null'
    }
  }
}
然后你可以这样使用它:

mapGen(items,function (item) {
    yield item.toUpperCase();
});
function *upper (items) {
  yield* items.mapGen(function * (item) {
    try {
      yield item.toUpperCase()
    } catch (e) {
      yield 'null'
    }
  })
}
var u = upper(['aaa','bbb','ccc']);
var uu = u.next().value; // the only value that upper will ever return
console.log(uu.next().value.next().value); // works
console.log(uu.next().value.next().value); // works
console.log(uu.next().value.next().value); // works
或者,如果你有勇气,你可以扩展
数组。prototype

// WARNING: UNTESTED!
Array.prototype.mapGen = function *mapGen (callback) {
    for (var i=0; i<this.length; i++) {
        yield callback(this[i])
    }
};
请注意,您需要两次屈服。这是因为内部收益率返回到
mapGen
,然后
mapGen
将产生该值,然后您需要从
上部
返回该值

嗯。这类方法有效,但不完全有效:

var u = upper(['aaa','bbb','ccc']);
console.log(u.next().value); // returns generator object
不完全是我们想要的。但这有点道理,因为第一个收益率返回一个收益率。所以我们把每一个收益作为一个生成器对象来处理?让我们看看:

var u = upper(['aaa','bbb','ccc']);
console.log(u.next().value.next().value.next().value); // works
console.log(u.next().value.next().value.next().value); // doesn't work
嗯。让我们找出第二个电话不起作用的原因

上层功能:

function *upper (items) {
  yield* items.mapGen(/*...*/);
}
生成
mapGen()
的返回值。现在,让我们忽略
mapGen
的功能,只考虑
yield
的实际含义

因此,我们第一次调用
.next()
时,函数在此处暂停:

function *upper (items) {
  yield* items.mapGen(/*...*/); // <----- yields value and paused
}
它返回(不是yield,因为该行上没有yield关键字)nothing(未定义)

这就是为什么第二个
console.log()
失败的原因:
*upper()
函数已经用完了要生成的对象。事实上,它只产生一次,所以它只有一个对象要产生——它是一个只产生一个值的生成器

嗯。所以我们可以这样做:

mapGen(items,function (item) {
    yield item.toUpperCase();
});
function *upper (items) {
  yield* items.mapGen(function * (item) {
    try {
      yield item.toUpperCase()
    } catch (e) {
      yield 'null'
    }
  })
}
var u = upper(['aaa','bbb','ccc']);
var uu = u.next().value; // the only value that upper will ever return
console.log(uu.next().value.next().value); // works
console.log(uu.next().value.next().value); // works
console.log(uu.next().value.next().value); // works
耶!但是,如果是这样,最内层的
如何在回调工作中产生

如果仔细想想,您会发现回调中最内层的
yield
也与
*upper()
中的
yield
类似,它只返回一个值。但我们从来不会使用它超过一次。这是因为第二次调用
uu.next()
时,我们不是返回同一个回调,而是返回另一个回调,而另一个回调将只返回一个值

所以它起作用了。也可以让它发挥作用。但这有点愚蠢

结论: 在所有这些之后,要了解为什么
yield
不能按我们预期的方式工作,关键点是
yield
暂停代码执行,然后在下一行继续执行。如果没有更多产量,则生成器终止(is
.done

要认识到的第二点是回调和所有那些数组方法(
.map
.forEach
等)并不是神奇的。它们只是javascript函数。因此,将它们视为
for
while
之类的控制结构有点错误

后记 有一种方法可以使
mapGen
干净地工作:

function upper (items) {
  return items.mapGen(function (item) {
    try {
      return item.toUpperCase()
    } catch (e) {
      return 'null'
    }
  })
}
var u = upper(['aaa','bbb','ccc']);
console.log(u.next().value);
console.log(u.next().value);
console.log(u.next().value);
但您会注意到,在本例中,我们返回回调(而不是yield),还返回
upper
。因此,这个案例在for循环中退化为一个
产量
,这不是我们要讨论的。

免责声明:我是workshopper的作者

@slebetman的回答有点正确,我还可以补充更多:

是的,在回调中不直接涉及
yield
。 但是,它告诉我们从您的
yield
item的位置获得的重要性,因为您只能在生成器内部使用
yield
。查看文档以了解更多信息

just fine solution在映射后更改的数组上迭代:

function *upper (items) {
  yield* items.map(function (item) {
    try {
      return item.toUpperCase();
    } catch (e) {
      return null;
    }
  });
}
我们可以这样做,因为数组有迭代机制,请参阅

没有默认的迭代行为,因此无法对其进行迭代

但是生成器不仅仅是迭代器。每个生成器都是迭代器,但反之亦然。生成器允许您通过调用
yield
关键字自定义迭代(而不仅仅是)过程。您可以在此处播放并查看生成器/迭代器之间的差异:


演示:。

您可以通过“co-npm”使用另一种方法:co.wrap(fn*)


我从未使用过收益率,所以最后一个例子可能是错误的。它可能需要回报而不是收益。在上一个示例中,您可能希望使用
yield*items.mapGen(…)
。或者使
upper
成为一个正常函数,并
返回items.mapGen(…)
。禁止使用。它仍然被屈服物品卡住了。toUpperCase()
@gyaresu:啊,是的。在这种情况下,
mapGen
的回调不应包含
yield
。它应该是一个
返回值
。在处理了这个问题后,我得出结论,它不适用于回调,因为它没有意义。注意:它可能看起来应该对人类有意义,但如果你像翻译一样思考,你会发现它没有意义。我将更新我的答案。通常,映射用于将一个数组转换为另一个数组。为什么这行不通?bit.ly/1YPHiYS-即a未定义-有办法吗?