Javascript jQuery-请向我解释闭包、变量上下文
好吧,我不明白为什么Firefox会说美元(“#canvas”)[0].getContext('2d');没有定义。我把它放在函数外,这样所有函数都可以访问它,但这里ctx仍然没有定义Javascript jQuery-请向我解释闭包、变量上下文,javascript,jquery,Javascript,Jquery,好吧,我不明白为什么Firefox会说美元(“#canvas”)[0].getContext('2d');没有定义。我把它放在函数外,这样所有函数都可以访问它,但这里ctx仍然没有定义 (function($) { // Undefined var ctx = $('#canvas')[0].getContext("2d"); var x = 150; var y = 150; var dx = 2;
(function($) {
// Undefined
var ctx = $('#canvas')[0].getContext("2d");
var x = 150;
var y = 150;
var dx = 2;
var dy = 4;
$(function() {
setInterval(draw, 10);
})
function draw() {
ctx.clearRect(0,0,300,300);
ctx.beginPath();
ctx.arc(x,y,10,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
x+=dx;
y+=dy;
}
})(jQuery);
但是,当我将ctx的位置转移到未命名函数时,ctx不是未定义的:
(function($) {
var ctx;
var x = 150;
var y = 150;
var dx = 2;
var dy = 4;
$(function() {
//Not Undefined
ctx = $("#canvas")[0].getContext('2d');
setInterval(draw, 10);
})
function draw() {
ctx.clearRect(0,0,300,300);
ctx.beginPath();
ctx.arc(x,y,10,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
x+=dx;
y+=dy;
}
})(jQuery);
第一个代码有什么问题?我的意思是var ctx在顶部声明。这将使它成为一个全局变量。嗯,我得到的错误是$(“#canvas”)[0]未定义。意味着它无法访问#画布。。为什么???这是因为在您的第一次调用中,您实际上正在创建一个函数对象,该对象将仅在加载DOM后在另一个上下文中进行处理 当页面中的所有元素都已加载时,将调用该匿名函数,因此调用者将是jQuery核心函数,其上下文与您在此处编写的上下文完全不同 我建议将所有内容包装在
$()
调用中,这样应该可以:
(function($) {
$(function() {
var ctx = $("#canvas")[0].getContext('2d');
var x = 150;
var y = 150;
var dx = 2;
var dy = 4;
setInterval(draw, 10);
function draw() {
ctx.clearRect(0,0,300,300);
ctx.beginPath();
ctx.arc(x,y,10,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
x+=dx;
y+=dy;
}
});
})(jQuery);
我想你搞错问题了。并不是您误解了变量上下文,而是您可能在声明canvas标记之前运行了javascript 下面的代码演示了这个问题。它将显示消息“canvasOne未定义!”,因为我们试图在声明之前访问
canvasOne
(注意
标记的位置)
我在这里创建了一个托管演示:(可编辑)
/*
浏览器一看到下面这行代码就立即运行它。
由于“canvasOne”标记尚未声明,因此变量将未定义。
*/
变量canvasOne=$('#canvasOne')[0];
$(函数(){
//以下代码在整个文档完成加载后运行。
if(canvasOne==未定义){
警报('canvasOne未定义!');
}
否则{
canvasOne.getContext(“2d”).fillRect(5,5,15,15);
}
});
/*
浏览器一看到下面这行代码就立即运行它。
但由于上面*声明了“canvasTwo”标记*,因此变量*不会*未定义。
*/
var canvasTwo=$('#canvasTwo')[0];
$(函数(){
//以下代码在整个文档完成加载后运行。
if(canvasTwo==未定义){
警报('canvasTwo未定义!');
}
否则{
canvasTwo.getContext(“2d”).fillRect(5,5,15,15);
}
});
$(函数(){
/*
以下代码在整个文档完成加载后运行。
因此,即使“canvastree”标记出现在代码后面,变量*不会*未定义。
*/
var canvastree=$(“#canvastree')[0];
if(canvastree==未定义){
警报('canvastree未定义!');
}
否则{
canvasThree.getContext(“2d”).fillRect(5,5,15,15);
}
});
Seb所说的是正确的。第一个不起作用,因为在您尝试获取画布对象时,它还没有实际加载。虽然您在回调中包装代码是正确的,但在上下文问题上是错误的。问题可能是javascript代码是在声明canvas标记之前运行的。我在回答中已经说明了这一点。谢谢。我只是在试验这东西的工作方式。我现在明白了。@ SEB对不起,如果我唠叨你,但是请考虑编辑你的答案来纠正或删除关于上下文的评论。除非我完全弄错了,否则它们只是不正确和误导。谢谢。@brian我真的不确定上下文问题;我相信我是对的,但现在我怀疑它,应该测试它@Rymn,你能告诉我们真正的问题是你在画布实际创建之前试图访问它吗?如果是这样,请将brian的答案标记为正确,而不是我的答案。谢谢
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<body>
<script>
/*
The following line of code is run as soon as the browser sees it.
Since the "canvasOne" tag is not declared yet, the variable will be undefined.
*/
var canvasOne = $('#canvasOne')[0];
$(function() {
// The following code is run after the whole document has finished loading.
if (canvasOne === undefined) {
alert('canvasOne is undefined!');
}
else {
canvasOne.getContext("2d").fillRect(5, 5, 15, 15);
}
});
</script>
<canvas id="canvasOne"></canvas>
<canvas id="canvasTwo"></canvas>
<script>
/*
The following line of code is run as soon as the browser sees it.
But since the "canvasTwo" tag *is* declared above, the variable will *not* be undefined.
*/
var canvasTwo = $('#canvasTwo')[0];
$(function() {
// The following code is run after the whole document has finished loading.
if (canvasTwo === undefined) {
alert('canvasTwo is undefined!');
}
else {
canvasTwo.getContext("2d").fillRect(5, 5, 15, 15);
}
});
</script>
<script>
$(function() {
/*
The following code is run after the whole document has finished loading.
Hence, the variable will *not* be undefined even though the "canvasThree" tag appears after the code.
*/
var canvasThree = $('#canvasThree')[0];
if (canvasThree === undefined) {
alert('canvasThree is undefined!');
}
else {
canvasThree.getContext("2d").fillRect(5, 5, 15, 15);
}
});
</script>
<canvas id="canvasThree"></canvas>
</body>
</html>