DOM
Window对象:
所有浏览器都支持 window 对象。
概念上讲.一个html文档对应一个window对象.
功能上讲: 控制浏览器窗口的.
使用上讲: window对象不需要创建对象,直接使用即可.
Window 对象方法
alert() 显示带有一段消息和一个确认按钮的警告框。
confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框。
prompt() 显示可提示用户输入的对话框。
open() 打开一个新的浏览器窗口或查找一个已命名的窗口。
close() 关闭浏览器窗口。
setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式。
clearInterval() 取消由 setInterval() 设置的 timeout。
setTimeout() 在指定的毫秒数后调用函数或计算表达式。
clearTimeout() 取消由 setTimeout() 方法设置的 timeout。
scrollTo() 把内容滚动到指定的坐标。
方法使用
1、alert、confirm、prompt、open:
alert('I can do it!') var flag= confirm('Are you sure?'); console.log(flag); //确定:True;取消:false //获取年龄 function getAge(){ var age = prompt('How old are you?'); if(isNaN(age)) { alert('that"is not Number'); getAge(); } else if(age >=18){ alert('恭喜你已成年!玩的愉快!'); // open参数:open(url,windowName,windowSize) open('http://www.xiaohuar.com','new','height=800,width=800') } else{ alert('哥们你还是未成年啊!'); } } 执行 getAge();
2、setInterval,clearInterval
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
语法:
setInterval(函数,时间(毫秒))
示例:
<input id="ID1" type="text" onclick="begin()"> <button onclick="end()">停止</button> <script> function showTime(){ var nowd2=new Date().toLocaleString(); var temp=document.getElementById("ID1"); temp.value=nowd2; } var ID; function begin(){ if (ID==undefined){ showTime(); ID=setInterval(showTime,1000); } } function end(){ clearInterval(ID); ID=undefined; } </script>
DOM 对象
- HTML Document Object Model(文档对象模型).
- HTML DOM 定义了访问和操作HTML文档的标准方法。
- HTML DOM 把 HTML 文档呈现为带有元素、属性和文本的树结构(节点树)。
DOM树:
画dom树是为了展示文档中各个对象之间的关系,用于对象的导航。
Dom节点:
HTML 文档中的每个成分都是一个节点。
DOM 是这样规定的:
整个文档是一个文档节点
每个 HTML 标签是一个元素节点
包含在 HTML 元素中的文本是文本节点
每一个 HTML 属性是一个属性节点
其中,document与element节点是重点。
节点关系:
节点树中的节点彼此拥有层级关系。
父(parent),子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点。同级的子节点被称为同胞(兄弟或姐妹)。
- 在节点树中,顶端节点被称为根(root):<html>
- 每个节点都有父节点、除了根(它没有父节点)
- 一个节点可拥有任意数量的子节点
- 同胞是拥有相同父节点的节点
下面的图片展示了节点树的一部分,以及节点之间的关系:
访问 HTML 元素(节点),访问 HTML 元素等同于访问节点,我们能够以不同的方式来访问 HTML 元素。
节点查找
直接查找节点:
注意:涉及到寻找元素,注意<script>标签的位置,最好将Script标签放到html最后或者将标签中的内容封装成函数(防止渲染之前获取元素)。
document.getElementById(“idname”) document.getElementsByTagName(“tagname”) document.getElementsByName(“name”) document.getElementsByClassName(“name”)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .button{ background-color: lightseagreen; font-size: 20px; } </style> </head> <body> <button class="button" onclick="change()">更改搜索</button> <div> 通过tag找到标签 <a href="http://www.sogou.com" id="sogou">搜索一下</a> <span name="s">通过name获取标签</span> </div> </body> <script> //更改超链接标签的内容 function change() { //通过id获取标签a var a1 = document.getElementById('sogou'); a1.href = 'http://www.baidu.com'; var font = a1.getElementsByTagName('font')[0]; font.innerHTML = '百度一下'; //通过class获取相同class名称的标签列表,获取第一个button,更改其中的文字 var button_1 = document.getElementsByClassName('button')[0]; button_1.innerText='停止'; } //通过tag获取 var div_1 = document.getElementsByTagName('div')[0]; console.log(div_1) </script> </html>
导航节点属性:
'''
parentElement // 父节点标签元素
children // 所有子标签
firstElementChild // 第一个子标签元素
lastElementChild // 最后一个子标签元素
nextElementtSibling // 下一个兄弟标签元素
previousElementSibling // 上一个兄弟标签元素 '''
注意,js中没有办法找到所有的兄弟标签!
节点操作
创建节点:
createElement(标签名) :创建一个指定名称的元素。
var tag=document.createElement(“input")
tag.setAttribute('type','text');
添加节点:
追加一个子节点(作为最后的子节点) somenode.appendChild(newnode) 把增加的节点放到某个节点的前边 somenode.insertBefore(newnode,某个节点);
删除节点:
somenode.removeChild(某个节点):通过父元素调用删除节点
替换节点:
somenode.replaceChild(newnode, 某个节点);
节点属性操作:
1、获取文本节点的值:innerText、innerHTML
2、attribute操作
elementNode.setAttribute(name,value)
elementNode.getAttribute(属性名)
elementNode.removeAttribute(“属性名”);
3、value-获取当前选中的value值:
1.input
2.select (selectedIndex 获取当前所选标签的index,然后通过children获取option集合来操作。)
3.textarea
4、innerHTML 给节点添加html代码:
该方法不是w3c的标准,但是主流浏览器支持
tag.innerHTML = “<p>要显示内容</p>”; - 赋值的时候也可以赋值标签
5、关于class的操作:
elementNode.className -获取当前元素class的值
elementNode.classList -获取当前元素class的列表 elementNode.classList.add elementNode.classList.remove
6、改变css样式:
<p id="p2">Hello world!</p> document.getElementById("p2").style.color="blue"; .style.fontSize=48px;
DOM Event(事件)
onclick 当用户点击某个对象时调用的事件句柄。
ondblclick 当用户双击某个对象时调用的事件句柄。
onfocus 元素获得焦点。 练习:输入框
onblur 元素失去焦点。 应用场景:用于表单验证,用户离开某个输入框时,代表已经输入完了,我们可以对它进行验证.
onchange 域的内容被改变。 应用场景:通常用于表单元素,当元素内容被改变时触发.(三级联动)
onkeydown 某个键盘按键被按下。 应用场景: 当用户在最后一个输入框按下回车按键时,表单提交.
onkeypress 某个键盘按键被按下并松开。
onkeyup 某个键盘按键被松开。
onload 一张页面或一幅图像完成加载。
onmousedown 鼠标按钮被按下。
onmousemove 鼠标被移动。
onmouseout 鼠标从某元素移开。
onmouseover 鼠标移到某元素之上。
onmouseleave 鼠标从元素离开
onselect 文本被选中。
onsubmit 确认按钮被点击。
绑定事件方式
方式1:
<div id="div" onclick="foo(this)">点我呀</div>
<script>
function foo(self){ // 形参不能是this;
console.log("点你大爷!");
console.log(self);
}
</script>
方式2:
<p id="abc">试一试!</p>
<script>
var ele=document.getElementById("abc");
ele.onclick=function(){
console.log("ok");
console.log(this); // this直接用
};
</script>
事件介绍
例:
onfocus、onblur、onchange、onload、onsubmit、事件穿透;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件</title> <style> *{ margin: 0px; } .big{ height: 200px; width: 200px; background-color: darkseagreen; } .small{ height: 100px; width: 100px; background-color: yellow; } </style> </head> <body> <!--onfocus 、onblur--> <input type="text" onfocus="input_str(this)" onblur="exit_input(this)" value="请输入"> <!--select-二级联动--> <select id="style_cooking"></select> <select id="dish"> <option>请选择菜品</option> </select> <!--obsubmit-form表单中提交按钮--> <form action="" method="post" id="form"> <input type="text"/> <input type="submit" value="提交"/> </form> <!--Event时间传递--> <div class="big"> <div class="small"></div> </div> </body> <script> // ===================input-输入框==================================== function input_str(self) { if(self.value=='请输入'){ self.value =''; } } function exit_input(self) { if(self.value ==''){ self.value ='请输入' } } // ===================select-二级联动 ==================================== info ={'请选择菜系':['请选择菜品'], '川菜':['鱼香肉丝','酸菜鱼','东坡肘子'], '东北菜':['锅包肉','溜肉段','杀猪菜'], '湘菜':['剁椒鱼头','金钱鱼']}; var cook_select = document.getElementById('style_cooking'); var dish_select = document.getElementById('dish'); // 给style_cooking添加菜系option for(var i in info){ var op = document.createElement('option'); op.innerText = i; cook_select.appendChild(op); } cook_select.onchange = function () { var index = this.selectedIndex; var cook_style = cook_select.children[index]; var change_name = cook_style.innerText; console.log('选择的菜系是',index,change_name); var dish_list = info[change_name]; console.log('菜单列表',dish_list); // 将dish_select中的元素清空 dish_select.options.length = 0; for(var i in dish_list){ var new_option = document.createElement('option'); new_option.innerText = dish_list[i]; dish_select.appendChild(new_option) } }; // ===================onlode 等待事物加载完成后再执行 ==================================== /*onload 属性开发中 只给 body元素加.这个属性的触发 标志着 页面内容被加载完成.应用场景: 当有些事情我们希望页面加载完立刻执行,那么可以使用该事件属性.*/ window.onload = function () { // 要执行的代码。 } // =================== obsubmit-form表单中提交按钮 ==================================== /*当表单在提交时触发. 该属性也只能给form元素使用.应用场景: 在表单提交前验证用户输入是否正确.如果验证失败.在该方法中我们应该阻止表单的提交.*/ var form_obj = document.getElementById('form'); console.log(form_obj); form_obj.onsubmit=function (event) { //第一种阻止提交的方式(常用) //onsubmit 命名的事件函数,可以接受返回值. 其中返回false表示拦截表单提交.其他为放行. return false; //第二种阻止提交方式: // 阻止表单提交方式2 event.preventDefault(); ==>通知浏览器不要执行与事件关联的默认动作。 event.preventDefault() } // 事件传递:两个带有事件的元素重叠,发生事件穿透。 window.onload= function () { var big_obj = document.getElementsByClassName('big')[0]; var small_obj = document.getElementsByClassName('small')[0]; big_obj.onclick=function (event) { alert('big_Click'); } small_obj.onclick = function (event) { // 阻止事件传递 event.stopPropagation(); alert('small_Click'); } } </script> </html>
onselect:当文本被选中的时候
<input type="text"> <script> var ele=document.getElementsByTagName("input")[0]; ele.onselect=function(){ alert(222); } </script>
onkeydown:
Event 对象:Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!event对象在事件发生时系统已经创建好了,并且会在事件函数被调用时传给事件函数.我们获得仅仅需要接收一下即可.比如onkeydown,我们想知道哪个键被按下了,需要问下event对象的属性,这里就时KeyCode.
<input type="text" id="t1"/> <script type="text/javascript"> var ele=document.getElementById("t1"); ele.onkeydown=function(e){ e=e||window.event; var keynum=e.keyCode; var keychar=String.fromCharCode(keynum); alert(keynum+'----->'+keychar); }; </script>
onmouseout与onmouseleave事件的区别:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #container{ width: 300px; } #title{ cursor: pointer; background: #ccc; } #list{ display: none; background:#fff; } #list div{ line-height: 50px; } #list .item1{ background-color: green; } #list .item2{ background-color: rebeccapurple; } #list .item3{ background-color: lemonchiffon; } </style> </head> <body> <p>先看下使用mouseout的效果:</p> <div id="container"> <div id="title">使用了mouseout事件↓</div> <div id="list"> <div class="item1">第一行</div> <div class="item2">第二行</div> <div class="item3">第三行</div> </div> </div> <script> // 1.不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。 // 2.只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。 var container=document.getElementById("container"); var title=document.getElementById("title"); var list=document.getElementById("list"); title.onmouseover=function(){ list.style.display="block"; }; container.onmouseleave=function(){ // 改为mouseout试一下 list.style.display="none"; }; /* 因为mouseout事件是会冒泡的,也就是onmouseout事件可能被同时绑定到了container的子元素title和list 上,所以鼠标移出每个子元素时也都会触发我们的list.style.display="none"; */ /* 思考: if: list.onmouseout=function(){ list.style.display="none"; }; 为什么移出第一行时,整个list会被隐藏? 其实是同样的道理,onmouseout事件被同时绑定到list和它的三个子元素item上,所以离开任何一个 子元素同样会触发list.style.display="none"; */ </script> </body> </html>
实例练习
1 菜单栏:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ margin: 0; padding: 0; } .left{ width: 20%; height: 500px; float: left; background-color: wheat; } .right{ float: left; width: 80%; height: 500px; background-color: lightgray; } .title{ text-align: center; line-height: 40px; background-color: #0e90d2; color: white; } .item{ padding: 10px; text-align: center; } .hide{ display: none; } </style> </head> <body> <div class="outer"> <div class="left"> <div class="item"> <div class="title">川菜</div> <ul class="con"> <li>鱼香肉丝</li> <li>酸菜鱼</li> <li>东坡肘子</li> </ul> </div> <div class="item"> <div class="title">东北菜</div> <ul class="con hide"> <li>锅包肉</li> <li>溜肉段</li> <li>杀猪菜</li> </ul> </div> <div class="item"> <div class="title">湘菜</div> <ul class="con hide"> <li>剁椒鱼头</li> <li>金钱鱼</li> <li>小炒肉</li> </ul> </div> </div> <div class="right"></div> </div> <script> var eles_title=document.getElementsByClassName("title"); for (var i=0;i<eles_title.length;i++){ eles_title[i].onclick=function(){ this.nextElementSibling.classList.remove("hide"); for(var j=0;j<eles_title.length;j++){ if (eles_title[j]!=this){ eles_title[j].nextElementSibling.classList.add("hide"); } } } } </script> </body> </html>
2 模态对话框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ margin: 0px; } .c1{ position:relative; height: 2000px; background:url("属性/gao.jpg"); } .c2{ position: fixed; background-color: silver; opacity: 0.4; top: 0px; right: 0px; bottom: 0px; left: 0px; } .c3{ height: 400px; width: 400px; background-color: blue; /*如果设置了Position属性,就必须设置位置*/ position: fixed; top:50%; left:50%; margin-top: -200px; margin-left: -200px; } .hide{ display: none; } </style> <script> var showFlag = true; function showLayer() { var elements = document.getElementsByClassName('button'); /*这里说一下为什么要多加一个button名字来,因为JavaScript是动态语言,如果我用hide来获取的话,在for循环的删除后,获取的elements就只剩下一个了所以再次获取的话就什么都得不到了。*/ for(var i=0;i<elements.length;i++){ if(showFlag){ elements[i].classList.remove('hide'); } else { elements[i].classList.add('hide'); } } if(showFlag){ showFlag=false; } else { showFlag=true; } } </script> </head> <body> <div class="c1"> <button onclick="showLayer()">showLayer</button> </div> <div class="c2 hide button"></div> <div class="c3 hide button"> <button onclick="showLayer()">closeLayer</button> </div> </body> </html>
3 表格案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button class="select_all">全选</button> <button class="select_reverse">反选</button> <button class="cancel">取消</button> <hr> <table class="server_table" border="2px" cellspacing="2px"> <tr> <td><input type="checkbox" class="item"></td> <td>111</td> <td>111</td> <td>111</td> </tr> <tr> <td><input type="checkbox" class="item"></td> <td>222</td> <td>222</td> <td>222</td> </tr> <tr> <td><input type="checkbox" class="item"></td> <td>333</td> <td>333</td> <td>333</td> </tr> <tr> <td><input type="checkbox" class="item"></td> <td>444</td> <td>444</td> <td>444</td> </tr> </table> <script> /* var ele_all=document.getElementsByClassName("select_all")[0]; var ele_reverse=document.getElementsByClassName("select_reverse")[0]; var ele_cancel=document.getElementsByClassName("cancel")[0]; var input_arr=document.getElementsByClassName("item"); ele_all.onclick=function(){ for(var i=0;i<input_arr.length;i++){ console.log(input_arr[i]); var input=input_arr[i]; input.checked=true; } }; ele_cancel.onclick=function(){ for(var i=0;i<input_arr.length;i++){ console.log(input_arr[i]); var input=input_arr[i]; input.checked=false; } }; ele_reverse.onclick=function(){ for(var i=0;i<input_arr.length;i++){ console.log(input_arr[i]); var input=input_arr[i]; if(input.checked){ input.checked=false; } else{ input.checked=true; } } }; */ var input_arr=document.getElementsByClassName("item"); var button_arr=document.getElementsByTagName("button"); for(var i=0;i<button_arr.length;i++){ button_arr[i].onclick=function(){ for (var j=0;j<input_arr.length;j++){ var inp=input_arr[j] if(this.innerText=="全选"){ console.log("ok"); inp.checked=true; } else if(this.innerText=="取消"){ inp.checked=false; } else { if(inp.checked){ inp.checked=false; }else { inp.checked=true; } } } } } </script> </body> </html>
5 select移动
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>移动</title> </head> <style> *{ margin:0; } #left,#right{ height: 200px; width: 200px; background-color: darkseagreen; } #mid{ display: inline-block; height: 200px; background-color: lightseagreen; vertical-align: top; } button{ margin-top: 10px; padding: 0 5px; } </style> <body> <select name="" id="left" multiple="multiple"> <option>水浒传</option> <option>西游记</option> <option>寻秦记</option> </select> <span id="mid"> <button id="move"> -> move </button><br> <button id="move_all"> ->move_all</button> </span> <select name="" id="right" multiple="multiple"> <option>红楼梦</option> <option>三国演义</option> <option>围城</option> </select> </body> <script> window.onload = function () { var move = document.getElementById('move'); var move_all = document.getElementById('move_all'); var left = document.getElementById('left'); var right = document.getElementById('right'); move.onclick = function () { for(var i=0; i<left.length;i++){ if(left[i].selected){ right.appendChild(left[i]); i--; } } } move_all.onclick =function () { for(var i=0;i<left.length;i++){ right.appendChild(left[0]); i--; } } } </script> </html>
6 跑马灯
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>跑马灯</title> <style> *{ margin: 0px; } #welcome{ color: white; background-color: darkseagreen; text-align: center; } </style> <script> var ID; function Press_button(self) { if(ID == undefined){ ID = setInterval('start()',200); // self.onclick='end()' self.innerHTML ='停止'; self.style.backgroundColor = 'red'; } else{ clearInterval(ID); ID = undefined; self.innerHTML = '开始'; self.style.backgroundColor = 'green'; } } function start() { var str_h1 = document.getElementById('welcome').innerText; var first = str_h1.substr(0,1); var after = str_h1.substr(1,str_h1.length-1); var new_str = after.concat(first); document.getElementById('welcome').innerText = new_str; } </script> </head> <body> <h1 id="welcome">北京欢迎你,为你开天辟地。</h1> <button onclick="Press_button(this)" style = color:white;background-color:green;>开始</button> </body> </html>
7 跑马灯与tab切换
js的作用域:
作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理。
任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
作用域
1. 全局作用域(Global Scope)
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说一下几种情形拥有全局作用域:
(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域
var name="111";
function foo(){
var age=23;
function inner(){
console.log(age);
}
inner();
}
console.log(name); // 111
//console.log(age); // Uncaught ReferenceError: age is not defined
foo(); // 23
inner(); // Uncaught ReferenceError: inner is not defined
(2)所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:
var name="111";
function foo(){
age=23;
var sex="male"
}
foo();
console.log(age); // 23
console.log(sex); // sex is not defined
变量blog拥有全局作用域,而sex在函数外部无法访问到。
(3)所有window对象的属性拥有全局作用域
一般情况下,window对象的内置属性都都拥有全局作用域,例如window.alert()、window.location、window.top等等。
2. 局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所有在一些地方也会看到有人把这种作用域成为函数作用域.
如示例1中的age与inner都只有局部作用域。(js中if、for没有自己的作用域)
作用域链(Scope Chain)
在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
示例演示
//-----**********************例1*********************************
var s=12;
function f(){
console.log(s);
var s=11; // s=11
console.log(s)
}
f(); // undefined 11
//-----**********************例2*********************************
var s=10;
function foo(){
console.log(s);
var s=5;
console.log(s);
function s(){console.log("ok")}// 函数的定于或声明是在词法分析时完成的,执行时已不再有任何操作
console.log(s);
}
foo(); function s 、5、5
//-----***********************例3********************************
function bar(age) {
console.log(age);
var age = 99;
var sex= 'male';
console.log(age);
function age() {
alert(123)
};
console.log(age);
return 100;
}
result=bar(5); 同上
//-----********************************************************
结果分析
当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。在函数bar创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图所示:
解析到函数调用时,即bar(5),会生成一个active object的对象,该对象包含了函数的所有局部变量、命名参数、参数集合以及this,然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。新的作用域链如下图所示:
过程解析:
function bar(age) {
console.log(age);
var age = 99;
var sex="male";
console.log(age);
function age(){
alert(123);
} ;
console.log(age);
return 100;
}
result=bar(5);
一 词法分析过程(涉及参数,局部变量声明,函数声明表达式):
1-1 、分析参数,有一个参数,形成一个 AO.age=undefine;
1-2 、接收参数 AO.age=5;
1-3 、分析变量声明,有一个 var age, 发现 AO 上面有一个 AO.age ,则不做任何处理
1-4 、分析变量声明,有一个 var sex,形成一个 AO.sex=undefine;
1-5 、分析函数声明,有一个 function age(){} 声明, 则把原有的 age 覆盖成 AO.age=function(){};
二 执行过程:
2-1 、执行第一个 console.log(age) 时,当前的 AO.age 是一个函数,所以输出的一个函数
2-2 、这句 var age=99; 是对不 AO.age 的属性赋值, AO.age=99 ,所以在第二个输出的age是 99;
2-3 、同理第三个输出的是 99, 因为中间没有改变 age 值的语句了。
注意:执行阶段:
function age(){
alert(123)
} ;
不进行任何操作,将执行语句复制给age这部操作是在词法分析时,即运行前完成的。
JavaScript函数执行过程是先解析,后执行。