我正在尝试使用Modernizr同时构建几个jsons,但它似乎打破了我的功能范围。 这很难解释所以看看这个例子,如果你不相信我就试试吧:
[1,2,3,4,5].forEach(function(i){
require("modernizr").build({}, function (result) {
console.log(i);
});
})
输出:
5
5
5
5
5
而不是预期的1,2,3,4,5,与任何类似的函数一样。
在我使用ECMAScript语言编写的所有年份之前,我没有遇到过这种行为,并且已经构建了我的项目(以及之前的项目)围绕着这样的想法,即你不能破坏这样的函数范围。
它基于承诺或甚至简单的回调打破任何系统。 这一天让我感到困惑,我无法找到合适的解决办法。 我甚至很难概念化导致这种情况发生的原因。 请帮忙。
编辑:
好的,看起来你们都挂在了forEach上...... 这是另一个让它更清晰的例子:function asd(i){
require("modernizr").build({}, function (result) {
console.log(i);
});
}
asd(1);
asd(2);
asd(3);
asd(4);
输出
4
4
4
4
究竟发生了什么?
答案 0 :(得分:0)
函数块是异步调用的,所以这种行为是预料之中的,因为这个调用比foreach的行走慢得多,所以当你到达function (result) {}
块时i
已经是5个
与Node.JS: How to pass variables to asynchronous callbacks?中描述的问题完全相同,您应该可以使用相同的解决方案
[1,2,3,4,5].forEach(function(i){
(function(i) {
require("modernizr").build({}, function (result) {
console.log(i);
});
})(i);
})
未经测试但有些像这样的工作
答案 1 :(得分:0)
Modernizr特有的问题不得不对全局变量进行破坏。
build
命令基本上是一个大的requirejs
配置函数,全部由大型配置对象提供支持。总有一些基本的东西是在函数顶部建立的
{
optimize: 'none',
generateSourceMaps: false,
optimizeCss: 'none',
useStrict: true,
include: ['modernizr-init'],
fileExclusionRegExp: /^(.git|node_modules|modulizr|media|test)$/,
wrap: {
start: '\n;(function(window, document, undefined){',
end: '})(window, document);'
}
}
然后,由于Modernizr在浏览器和节点中都可以不做任何更改,因此需要有一种方法让它知道它是应该通过文件系统还是通过http加载它的依赖项。所以我们在环境检查中添加了一些像basePath这样的选项
if (inBrowser) {
baseRequireConfig.baseUrl = '/i/js/modernizr-git/src';
} else {
baseRequireConfig.baseUrl = __dirname + '/../src';
}
此时,配置对象被传递到requirejs.config
,这需要连线,并允许我们开始调用build
。
最后,在创建了所有这些之后,我们还有一个构建函数,它还会再次修改配置对象以进行构建特定设置(构建中的实际检测,正则表达式以消除某些AMD crud等)
所以这是一个超级简化的伪代码版本,最终发生了什么
var config = {
name: 'modernizr'
}
if (inBrowser) {
config.env = 'browser';
} else {
config.env = 'node';
}
requirejs.config(config);
module.exports = function(config, callback) {
config.out = function (output) {
//code to strip out AMD ceremony, add classPrefix, version, etc
callback(output)
}
requirejs.optimize(config)
}
发现问题?
因为在运行异步require.optimize函数之前,我们正在触及配置对象的.out
方法(其范围是整个模块,因此它的上下文在build()
调用之间保存) ,每次调用.out
时,您传递的回调都会重写build
方法。
这应该在Modernizr中用几个小时修复