进入这个转换流行为,我无法解释。首先是设置:
var pass = new require('stream').PassThrough
var numbers = ['one:', 'two:', 'three:', 'four:', 'five:', 'six:', 'seven:', 'eight:', 'nine:', 'ten:']
pass.pipe(process.stdout)
好的,现在当我使用forEach
写入流时,我得到以下预期的行为:
numbers.forEach(function(val) {
pass.write(val)
})
# one:two:three:four:five:six:seven:eight:nine:ten:
但是!如果我以这种稍微不同的方式写入流,我会得到以下意外的行为:
numbers.forEach(pass.write.bind(pass))
# one:tthfoufivesix:seven:eight:nine:ten:
所以我的问题是,为什么不同的输出?我在这里错过了什么吗?
我正在运行v0.10.30
答案 0 :(得分:3)
.forEach
将多个参数传递给回调,因此当您直接传递回调时,您并不只是将val
传递给回调,您也传递了数组索引和整个数组到.write
。
你的等价比较是错误的:
numbers.forEach(pass.write.bind(pass));
与
相同numbers.forEach(function(val) {
pass.write(val)
});
它等同于:
numbers.forEach(function() {
pass.write.apply(pass, arguments);
});
或更具体地说:
numbers.forEach(function(val, index, array) {
pass.write(val, index /* encoding */, array /* cb */);
});
当您查看.write(chunk, encoding, cb)
的签名时,如果它不是函数,则会忽略回调,因此您实际上正在执行.write(val, index)
。疯狂的输出是因为这些值在写入之前传递到Buffer
,所以你实际上是在调用它:
numbers.forEach(function(val, index, array) {
pass.write(new Buffer(val, index /* encoding */));
});
分解成这样的东西:
numbers.forEach(function(val, index, array) {
var b = new Buffer(...);
b.write(val, index /* encoding */);
pass.write(b);
});
这就是魔术发生的地方。 Buffer.prototype.write
的签名是
.write(string, [offset], [length], [encoding])
由于您将编码作为数字而不是实际编码传递,因此使用编码值作为长度而不是编码进行调用,因此您将根据数组索引对字符串长度进行切片。