须知
1.函数只有被声明(var fn=...)后,才能被读(...=fn return fn)或写(fn())
2.下述中的匿名函数可以用回调函数代替
分析以下代码中各个函数被声明或调用的顺序
setTimeout
先声明fn,再声明setTimeout
var fn=function(){
console.log('setTimeout起效果')
}
setTimeout(fn, 1000)
// setTimeout起效果
fn被声明------>setTimeout被声明------>setTimeout(fn)被调用
先声明setTimeout,再声明fn
setTimeout(fn, 1000)
var fn=function(){
console.log('qa')
}
//报错
使用匿名函数
var ft=function(){
setTimeout(fn, 1000) //只有当ft()被调用时,setTimeout()才被声明并调用
}
var fn=function(){
console.log('qa')
}
ft()
//'setTimeout起效果'
ft被声明------> fn被声明------>ft()被调用------> setTimeout被声明------>setTimeout(fn)被调用
采用function a(){...}命名方式
setTimeout(fn, 1000) // setTimeout起效果
function fn(){
console.log('qa')
}
onclick
先声明onclick,再声明fnclick
var oDiv=document.getElementById("div")
oDiv.onclick=fnclick
var fnclick=function(){
alert('onclick起效果')
}
// 报错
先声明fnclick,再声明onclick
var oDiv=document.getElementById("div")
var fnclick=function(){
alert('onclick起效果')
}
oDiv.onclick=fnclick
//onclick起效果
fnclick被声明------>oDiv.onclick被声明
---(按下鼠标)--->oDiv.onclick(fnclick被调用)
使用匿名函数
var oDiv=document.getElementById("div")
oDiv.onclick=function(){
fnclick() //只有当oDiv.onclick被调用时,fnclick才被
}
var fnclick=function(){
alert('onclick起效果')
}
oDiv.onclick被声明------>fnclick被声明
---(按下鼠标)--->oDiv.onclick(fnclick被调用)
一个较复杂的例子
var oDiv
var disX
var disY
oDiv=document.getElementById("div")
var fndown=function(ev){
disX=ev.clientX-oDiv.offsetLeft
disY=ev.clientY-oDiv.offsetTop
oDiv.onmousemove=fnmove //只有当fndown()被调用时oDiv.onmousemove才被声明,注意此处fnmove没有被调用
}
oDiv.onmousedown=fndown
var fnmove=function(ev){
oDiv.style.left=ev.clientX-disX+'px'
oDiv.style.top=ev.clientY-disY+'px'
oDiv.onmouseup=fnup //只有当fnmove()被调用时oDiv.onmouseup才被声明,注意此处fnup没有被调用
}
var fnup=function(){
oDiv.onmouseup=null
oDiv.onmousemove=null
}
fndown被声明------>oDiv.onmousedown被声明------>fnmove被声明------>fnup被声明
---(按下鼠标)--->oDiv.onmousedown(fndown)被调用------>oDiv.onmousemove被声明
---(移动鼠标)--->oDiv.onmousemove(fnmove)被调用------>oDiv.onmouseup被声明
---(松开鼠标)--->oDiv.onmouseup(fnup)被调用
用回调函数
var callback=function(ev){
fndown(ev)
}
var oDiv
var disX
var disY
oDiv=document.getElementById("div")
oDiv.onmousedown=callback //匿名函数可以和回调函数互相转化
var fndown=function(ev){
disX=ev.clientX-oDiv.offsetLeft
disY=ev.clientY-oDiv.offsetTop
oDiv.onmousemove=fnmove //这里fnmove只是被读
}
var fnmove=function(ev){
oDiv.style.left=ev.clientX-disX+'px'
oDiv.style.top=ev.clientY-disY+'px'
oDiv.onmouseup=fnup
}
var fnup=function(){
oDiv.onmouseup=null
oDiv.onmousemove=null
}
callback被声明------>oDiv.onmousedown被声明-------> fndown被声明------>fnmove被声明------>fnup被声明
---(按下鼠标)--->oDiv.onmousedown(callback/fndown)被调用------>oDiv.onmousemove被声明
---(移动鼠标)--->oDiv.onmousemove(fnmove)被调用------>oDiv.onmouseup被声明
---(松开鼠标)--->oDiv.onmouseup(fnup)被调用
结论
1.js中函数声明顺序为从上至下,某个函数在读或写前必须被声明过。
2.异步函数的调用(执行)是异步的,但声明仍然是同步的。涉及的函数必须先于异步函数声明。