Javascript 变量范围和对象作为参数传递给函数
Javascript variable scope and object passed as argument to function
我正在使用 Laravel Elixir 和 Laravel-Elixir-SpriteSmith 创建一些精灵图标。我至少有 3 个不同的图标大小存储在不同的文件夹中,所以我尝试遍历这些文件夹并执行为每个文件夹生成精灵的任务:
我的问题是,在传递给 mix.spritesmith
的第二个参数的 cssOpts.cssSelector
函数中,set
的值始终是最后一个值。
代码解释得更好:
var sources = [
{ size: 16, source: 'resources/bower_components/famfamfam-silk/dist/png' },
{ size: 22, source: 'resources/assets/icons/22' },
{ size: 38, source: 'resources/assets/icons/38' }
];
for(var i in sources) {
var set = sources[i];
mix.spritesmith(set.source, {
imgOutput: 'public/icons',
cssOutput: 'public/css',
imgName: set.size + '.png',
cssName: 'icons-' + set.size + '.css',
imgPath: '../../icons/' + set.size + '.png',
cssOpts: {
cssSelector: function(item) {
console.log(set.size); //PROBLEM HERE. Always prints 38! Should print 16 - 22 - 38.
return '.icon' + set.size + '-' + item.name.replace('_', '-');
}
}
});
}
我应该怎么做才能在每个循环中将正确的值传递给函数?
您遇到的问题称为后期绑定。您可以在多个 SO 问题上阅读它,例如:Late binding onclick event
你基本上需要创建一个新的作用域,它会绑定一个 set
的特定值。
cssSelector: (function(innerSet) {
return function(item) {
console.log(innerSet.size);
return '.icon' + innerSet.size + '-' + item.name.replace('_', '-');
};
})(set)
我同意其他人的看法,这是由于闭包和变量提升在 javascript 中的工作方式:var set
是上层函数作用域的一部分,而不是循环。因此,在执行 cssSelector
时,set
等于数组中的最后一个元素。
您可以使用@ralh 的方式,或者使用 forEach 方法:
var sources = [{
size: 16,
source: 'resources/bower_components/famfamfam-silk/dist/png'
}, {
size: 22,
source: 'resources/assets/icons/22'
}, {
size: 38,
source: 'resources/assets/icons/38'
}];
sources.forEach(function (set) {
mix.spritesmith(set.source, {
imgOutput: 'public/icons',
cssOutput: 'public/css',
imgName: set.size + '.png',
cssName: 'icons-' + set.size + '.css',
imgPath: '../../icons/' + set.size + '.png',
cssOpts: {
cssSelector: function(item) {
console.log(set.size); //PROBLEM HERE. Always prints 38! Should print 16 - 22 - 38.
return '.icon' + set.size + '-' + item.name.replace('_', '-');
}
}
});
})
我正在使用 Laravel Elixir 和 Laravel-Elixir-SpriteSmith 创建一些精灵图标。我至少有 3 个不同的图标大小存储在不同的文件夹中,所以我尝试遍历这些文件夹并执行为每个文件夹生成精灵的任务:
我的问题是,在传递给 mix.spritesmith
的第二个参数的 cssOpts.cssSelector
函数中,set
的值始终是最后一个值。
代码解释得更好:
var sources = [
{ size: 16, source: 'resources/bower_components/famfamfam-silk/dist/png' },
{ size: 22, source: 'resources/assets/icons/22' },
{ size: 38, source: 'resources/assets/icons/38' }
];
for(var i in sources) {
var set = sources[i];
mix.spritesmith(set.source, {
imgOutput: 'public/icons',
cssOutput: 'public/css',
imgName: set.size + '.png',
cssName: 'icons-' + set.size + '.css',
imgPath: '../../icons/' + set.size + '.png',
cssOpts: {
cssSelector: function(item) {
console.log(set.size); //PROBLEM HERE. Always prints 38! Should print 16 - 22 - 38.
return '.icon' + set.size + '-' + item.name.replace('_', '-');
}
}
});
}
我应该怎么做才能在每个循环中将正确的值传递给函数?
您遇到的问题称为后期绑定。您可以在多个 SO 问题上阅读它,例如:Late binding onclick event
你基本上需要创建一个新的作用域,它会绑定一个 set
的特定值。
cssSelector: (function(innerSet) {
return function(item) {
console.log(innerSet.size);
return '.icon' + innerSet.size + '-' + item.name.replace('_', '-');
};
})(set)
我同意其他人的看法,这是由于闭包和变量提升在 javascript 中的工作方式:var set
是上层函数作用域的一部分,而不是循环。因此,在执行 cssSelector
时,set
等于数组中的最后一个元素。
您可以使用@ralh 的方式,或者使用 forEach 方法:
var sources = [{
size: 16,
source: 'resources/bower_components/famfamfam-silk/dist/png'
}, {
size: 22,
source: 'resources/assets/icons/22'
}, {
size: 38,
source: 'resources/assets/icons/38'
}];
sources.forEach(function (set) {
mix.spritesmith(set.source, {
imgOutput: 'public/icons',
cssOutput: 'public/css',
imgName: set.size + '.png',
cssName: 'icons-' + set.size + '.css',
imgPath: '../../icons/' + set.size + '.png',
cssOpts: {
cssSelector: function(item) {
console.log(set.size); //PROBLEM HERE. Always prints 38! Should print 16 - 22 - 38.
return '.icon' + set.size + '-' + item.name.replace('_', '-');
}
}
});
})