为什么我的变量在 array.forEach 的嵌套函数中使用 undefined in Javascript
why is my variable in a nested function with array.forEach use undefined in Javascript
如果这里的答案很明显,我很抱歉,我主要是 c/c++ 人,javascript 对我来说比较陌生。
我正在使用三个,与 browserify 捆绑在一起。在一个模块中,我正在创建一个网格 object 数组,我需要使用 forEach(...) 在嵌套函数中访问它,但我不断收到错误,相应的 object 是没有定义的。我怀疑这个问题与我实际上在一个单独的回调函数中定义数组有关,该回调函数是使用 forEach() 与嵌套函数并行定义的。在将变量分配给回调函数中的数组之前,我一直在尝试全局“声明”该变量,但这不起作用。在 c++ 中,我会全局定义一个未实例化的 object(或在 class header 中),然后稍后在某个函数中实例化它,同时在之后的另一个函数中访问它。下面是相关代码,不断返回未定义的变量称为“网格”。请注意,我什至不确定为什么 setPallete(...) 和 update(...) 被实现为嵌套函数(对我来说是一个奇怪的概念)?在此代码的另一个化身中,我将它们实现为“独立”(例如,非嵌套)函数并且一切正常,但在该代码中我没有使用 browserify 进行捆绑,因为我只有一个单一的脚本。所以这可能与此有关。
感谢您的帮助。
let mesh; //try global definition -- no dice
module.exports = function (app) {
const totalMeshes = 40;
const subdivisions = 300;
const numSides = 8;
const openEnded = false;
const geometry = createGeometry(numSides, subdivisions, openEnded);
const container = new THREE.Object3D();
const lines = newArray(totalMeshes);
ShaderLoader("scripts/Grp3D/lib/shaders/tube.vert", "scripts/Grp3D/lib/shaders/tube.frag", function (vertex, fragment) {
const baseMaterial = new THREE.RawShaderMaterial({
vertexShader: vertex,
fragmentShader: fragment,
side: THREE.FrontSide,
extensions: {
deriviatives: true
},
defines: {
lengthSegments: subdivisions.toFixed(1),
ROBUST: false,
ROBUST_NORMALS: false,
FLAT_SHADED: true
},
uniforms: {
thickness: { type: 'f', value: 1 },
time: { type: 'f', value: 0 },
color: { type: 'c', value: new THREE.Color('#303030') },
animateRadius: { type: 'f', value: 0 },
animateStrength: { type: 'f', value: 0 },
index: { type: 'f', value: 0 },
totalMeshes: { type: 'f', value: totalMeshes },
radialSegments: { type: 'f', value: numSides }
}
});
lines.map((_, i) => {
const t = totalMeshes <= 1 ? 0 : i / (totalMeshes - 1);
const material = baseMaterial.clone();
material.uniforms = THREE.UniformsUtils.clone(material.uniforms);
material.uniforms.index.value = t;
material.uniforms.thickness.value = randomFloat(0.005, 0.0075);
mesh = new THREE.Mesh(geometry, material);
mesh.frustumCulled = false; // to avoid ThreeJS errors
return mesh;
});
lines.forEach(tmesh => container.add(tmesh));
});
return {
object3d: container,
update,
setPalette
};
// animate in a new color palette
function setPalette (palette) {
tweenr.cancel();
lines.forEach((mesh, i) => {
const uniforms = mesh.material.uniforms;
uniforms.color.value.set(palette);
const delay = i * 0.004;
uniforms.animateRadius.value = 0;
uniforms.animateStrength.value = 1;
tweenr.to(uniforms.animateRadius, { value: 1, duration: 0.5, delay, ease: 'epxoOut' });
tweenr.to(uniforms.animateStrength, { value: 0, duration: 1, delay, ease: 'expoInOut' });
});
}
function update (dt) {
dt = dt / 1000;
lines.forEach(mesh => { //undefined when the code runs
mesh.material.uniforms.time.value += dt;
});
}
};
这里有几个问题:
错误const lines = newArray(totalMeshes);
正确 const lines= []; //In Js its not necessary to have a predefined length.
您还需要将数据放在上面的行数组中。
希望我做对了。您可能是指容器变量等,对吗?
我看到的问题是您正在向带有两个参数的 ShaderLoader 添加匿名回调函数。这个函数在 ShaderLoader 的某处被调用。在 ShaderLoader 的范围内,您的变量容器等不再可用。
您在这里使用的是 const,它是块范围的。我发现 an article 很好地解释了它。
如果这里的答案很明显,我很抱歉,我主要是 c/c++ 人,javascript 对我来说比较陌生。
我正在使用三个,与 browserify 捆绑在一起。在一个模块中,我正在创建一个网格 object 数组,我需要使用 forEach(...) 在嵌套函数中访问它,但我不断收到错误,相应的 object 是没有定义的。我怀疑这个问题与我实际上在一个单独的回调函数中定义数组有关,该回调函数是使用 forEach() 与嵌套函数并行定义的。在将变量分配给回调函数中的数组之前,我一直在尝试全局“声明”该变量,但这不起作用。在 c++ 中,我会全局定义一个未实例化的 object(或在 class header 中),然后稍后在某个函数中实例化它,同时在之后的另一个函数中访问它。下面是相关代码,不断返回未定义的变量称为“网格”。请注意,我什至不确定为什么 setPallete(...) 和 update(...) 被实现为嵌套函数(对我来说是一个奇怪的概念)?在此代码的另一个化身中,我将它们实现为“独立”(例如,非嵌套)函数并且一切正常,但在该代码中我没有使用 browserify 进行捆绑,因为我只有一个单一的脚本。所以这可能与此有关。
感谢您的帮助。
let mesh; //try global definition -- no dice
module.exports = function (app) {
const totalMeshes = 40;
const subdivisions = 300;
const numSides = 8;
const openEnded = false;
const geometry = createGeometry(numSides, subdivisions, openEnded);
const container = new THREE.Object3D();
const lines = newArray(totalMeshes);
ShaderLoader("scripts/Grp3D/lib/shaders/tube.vert", "scripts/Grp3D/lib/shaders/tube.frag", function (vertex, fragment) {
const baseMaterial = new THREE.RawShaderMaterial({
vertexShader: vertex,
fragmentShader: fragment,
side: THREE.FrontSide,
extensions: {
deriviatives: true
},
defines: {
lengthSegments: subdivisions.toFixed(1),
ROBUST: false,
ROBUST_NORMALS: false,
FLAT_SHADED: true
},
uniforms: {
thickness: { type: 'f', value: 1 },
time: { type: 'f', value: 0 },
color: { type: 'c', value: new THREE.Color('#303030') },
animateRadius: { type: 'f', value: 0 },
animateStrength: { type: 'f', value: 0 },
index: { type: 'f', value: 0 },
totalMeshes: { type: 'f', value: totalMeshes },
radialSegments: { type: 'f', value: numSides }
}
});
lines.map((_, i) => {
const t = totalMeshes <= 1 ? 0 : i / (totalMeshes - 1);
const material = baseMaterial.clone();
material.uniforms = THREE.UniformsUtils.clone(material.uniforms);
material.uniforms.index.value = t;
material.uniforms.thickness.value = randomFloat(0.005, 0.0075);
mesh = new THREE.Mesh(geometry, material);
mesh.frustumCulled = false; // to avoid ThreeJS errors
return mesh;
});
lines.forEach(tmesh => container.add(tmesh));
});
return {
object3d: container,
update,
setPalette
};
// animate in a new color palette
function setPalette (palette) {
tweenr.cancel();
lines.forEach((mesh, i) => {
const uniforms = mesh.material.uniforms;
uniforms.color.value.set(palette);
const delay = i * 0.004;
uniforms.animateRadius.value = 0;
uniforms.animateStrength.value = 1;
tweenr.to(uniforms.animateRadius, { value: 1, duration: 0.5, delay, ease: 'epxoOut' });
tweenr.to(uniforms.animateStrength, { value: 0, duration: 1, delay, ease: 'expoInOut' });
});
}
function update (dt) {
dt = dt / 1000;
lines.forEach(mesh => { //undefined when the code runs
mesh.material.uniforms.time.value += dt;
});
}
};
这里有几个问题:
错误const lines = newArray(totalMeshes);
正确 const lines= []; //In Js its not necessary to have a predefined length.
您还需要将数据放在上面的行数组中。
希望我做对了。您可能是指容器变量等,对吗? 我看到的问题是您正在向带有两个参数的 ShaderLoader 添加匿名回调函数。这个函数在 ShaderLoader 的某处被调用。在 ShaderLoader 的范围内,您的变量容器等不再可用。 您在这里使用的是 const,它是块范围的。我发现 an article 很好地解释了它。