我正在尝试使用 Modernizr 一次构建多个 json,但它似乎破坏了我的函数范围。 这很难解释,所以看看这个例子,如果你不相信我,就试试吧:
[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 的语言进行编码的这些年里,我从未遇到过这种行为,并且围绕这样的想法构建了我的项目(以及之前的项目):不能像这样破坏函数的作用域。
它会破坏任何基于 promise 甚至简单回调的系统。 这让我困惑了一整天,找不到合适的解决办法。 我什至很难想象是什么导致了这种情况的发生。 请帮忙。
编辑:
好吧,看起来你已经对 forEach 挂断了...... 这是另一个例子,可以让它更清楚一点:
function asd(i){
require("modernizr").build({}, function (result) {
console.log(i);
});
}
asd(1);
asd(2);
asd(3);
asd(4);
输出
4
4
4
4
到底发生了什么?
最佳答案
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 无需更改即可在浏览器和 Node 中工作,因此需要有一种方法让它知道是否应该通过文件系统或通过 http 加载其依赖项。因此,我们在环境检查中添加了更多选项,例如 basePath
if (inBrowser) {
baseRequireConfig.baseUrl = '/i/js/modernizr-git/src';
} else {
baseRequireConfig.baseUrl = __dirname + '/../src';
}
此时,配置对象被传递到 requirejs.config
中,它连接了 require 并允许我们开始调用 build
。
最后,在创建所有这些之后,我们有一个构建函数,它最终还会再次修改配置对象以进行特定于构建的设置(构建中的实际检测、正则表达式以删除一些 AMD crud 等)。
所以这是最终发生的事情的 super 简化伪代码版本
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()
调用之间保存),因此每次调用 build
时,您传递的回调都会重写 .out
方法。
这应该在 Modernizr 中几个小时内修复
关于javascript - 当我在 Node JS 中调用 Modernizr.build 时,范围行为非常不寻常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34773567/