学完了js的基础语法和DOM之后,就要要看看javascript中最后一项BOM了。BOM,全称brower document model,翻译过来就是浏览器对象模型。DOM是文档对象模型,属于BOM中的很重要的一部分。而BOM除了包含DOM之外,还有很对其他的对象。我们所说的BOM就是整个浏览器,他除了展示给我文档对象模型之外(也就是展示的页面),还有地址栏,前进后退和刷新之类的。这些东西合起来就是BOM了。我们知道,DOM是一些用来操作页面元素的API,而BOM操作的则是浏览器。
说到BOM,就不得不提到window对象了。window对象是javascript中的顶级对象,所有定义在全局作用域中的变量、函数都会变成window对象的属性和方法。因为他是javascript中的顶级对象,所以在调用window对象下的属性和方法时可以省略window。比如下面这段代码,我们在全局作用域中定义了一个变量a=0,我们在控制台中分别输出a和window.a的值,他们的输出结果都是一样的,都为0。这就是因为a是定义在全局作用域下的变量,所以在调用的时候a变成了window对象的属性。它的值为0。而window对象下的属性在调用的时候可以省略window,所以他们输出的结果是一样的。
var a=0; console.log(a); console.log(window.a);
其实在最开始学js的时候我们就已经接触过一些window对象的方法了。比如:
alert(); confirm();
这两种方法其实都是window对象的方法,我们可以把它写成下面的样式,他们的效果都是一样的。
window.alert("asd"); window.confirm("asd");
window对象除了有这些方法之外,还有很多其他的方法,比如window.open();用来打开一个网址,他有四个参数,第一个参数是用来填写要打开的网址的,第二个参数则声明了新窗口的名称,第三个参数则声明了新窗口要显示的标准浏览器的特征,第四个参数则是一个boolean值,来判断是否在新窗口中打开。这个方法具体的参数属性可以直接在w3c上查到,所以我这就不多说,我们只要知道open()方法是用来打开新页面就好了。
好了,知道了这些了解性的内容之后,就要说说BOM中经常用到的内容:定时器。定时器分两种,一种是setTimeout()。另一种是setInterval(),那这两种定时器又有什么区别呢?
首先来讲讲setTimeout()方法;它用于在指定的毫秒数后调用函数或计算表达式。这个方法有两个参数,这里我们先说说第二个参数。第二个参数定义的是要等待的毫秒数,那等待这些毫秒数有什么意义呢?这时候,就要用到第一个参数了,第一个参数的内容是过了等待毫秒数之后要执行的代码。所以说,第一个参数是一个要执行的代码段。通常情况下,这个参数是一个匿名函数,也有可能是一个函数的函数名。比如下面三种方式都是可以实现输出一句话的效果的。
//第一种 setTimeout(function () { alert("啦啦啦"); },500); //第二种 setTimeout("alert(‘啦啦啦‘)",500); //第三种 setTimeout(lalala,500); function lalala(){ alert("啦啦啦"); }
下面来说说第二种方法,setInterval();这种方法跟前一个方法很类似,他也有两个参数。第一个参数也是后一个参数定义的毫秒数到达后要执行的代码。不同的是,这个方法他是不停的执行第一个参数中的代码段。而第二个参数定义的则是间隔的事件。比如下面的代码,他会每隔一秒不停的跳出弹框。
setInterval(function () { alert("啦啦啦"); },1000)
既然可以设置定时器,同样的,也可以删除定时器。setTimeout()方法对应的关闭定时器的方法是clearTimerout();而setInterval()方法对应的关闭定时器的方法是clearInterval();关闭定时器的方法最好是和设置的定时器相对应。下面来看看如何清除setInterval()这个定时器。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> div { width: 200px; height: 200px; position: absolute; } </style> </head> <body> <input type="button" value="开始移动" id="btn1"/> <input type="button" value="清除定时器" id="btn2"/> <div id="demo"></div> <script> var demo =document.getElementById("demo"); var btn1 = document.getElementById("btn1"); var btn2 = document.getElementById("btn2"); var timeId = null; btn1.onclick = function(){ clearInterval(timeId); timeId = setInterval(function(){ var step = 10; var leader = demo.offsetLeft; leader = leader + step; demo.style.left = leader + ‘px‘; },50); } btn2.onclick = function(){ clearInterval(timeId); } </script> </body> </html>
上述代码定义了两个input按钮和一个div盒子。在点击开始移动按钮时,盒子向右移动,在点击清除定时器的时候,盒子停止运动。在这里有一个注意点,在点击开始移动按钮时,先清空了一下定时器,之后在开启定时器。这样做的好处就是,如果不停的点击开始移动按钮,不会生成很多个定时器,使得右移的速度不断加快。
上面的代码中用到了一个offsetLeft属性,获取的是元素距离有定位的父盒子的左边距。这么说可能有点绕,下面就来详细的说说offset系列的属性。
offsetWidth和offsetHeight。这个两个属性分别可以获取元素的宽和高,比如以下代码:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> #d { height: 200px; width: 150px; padding: 30px; border: 10px solid #000; margin: 20px; } </style> </head> <body> <div id="d"></div> <script> var d = document.getElementById("d"); console.log(d.offsetWidth); console.log(d.offsetHeight); </script> </body> </html>
上述代码在控制台中输出的结果分别是230和280,并且都是不带单位的。由此我们可知他们获取的分别是盒子的宽度和高度,并且这个宽高是包括边框和内边距的,但不包括外边距。这时候我们可能会想到另一种获取宽高的方式。就是用style。这时候我们更改一下代码:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> #d { height: 200px; width: 150px; padding: 30px; border: 10px solid #000; margin: 20px; } </style> </head> <body> <div id="d"></div> <script> var d = document.getElementById("d"); console.log(d.style.width); console.log(d.style.height); </script> </body> </html>
这是因为用style的方式获取的属性只能是行内式的属性,也就是标签内写的属性。否则的话就会获取不到。所以这种情况下,我们就只能用offset系列的属性来获取它的宽高。不过offset系列的属性都是只读的,也就是说,我们通过offset系列的属性只能获取到元素的属性,而不能更改用他来更改元素的属性。
下面再来看看offsetLeft和offsetTop;首先来看看offsetLeft;
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; } #d1 { width: 500px; height: 500px; /*position: absolute;*/ /*left: 50px;*/ margin-left: 60px; border: 30px solid yellow; } #d { height: 200px; background-color: red; padding: 30px; border: 10px solid #000; width: 200px; } </style> </head> <body> <div id="d1"> <div id="d" style="left: 30px"></div> </div> <script> var d = document.getElementById("d"); console.log(d.offsetLeft); </script> </body> </html>
上述代码输出的结果为90;这时候,我们给父盒子设置定位并且把左外边距注释掉。我们会发现,输出的结果变成0了。
#d1 { width: 500px; height: 500px; position: absolute; left: 50px; /*margin-left: 60px;*/ border: 30px solid yellow; }
这是因为offsetLeft是当前盒子的外边框距离定位的父盒子的内边框的距离,如果父级元素没有定位的话,默认是以文档的左侧为准。而如果父盒子有定位,则是当前盒子的外边框到定位的父盒子的内边框的距离。offsetTop跟offsetLeft的属性相同,只不过他是相对于父盒子上内边距的距离或者文档的上方为准。