BOM基础(一)

  学完了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,我们在控制台中分别输出awindow.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系列的属性。

  offsetWidthoffsetHeight。这个两个属性分别可以获取元素的宽和高,比如以下代码:

<!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>

  上述代码在控制台中输出的结果分别是230280,并且都是不带单位的。由此我们可知他们获取的分别是盒子的宽度和高度,并且这个宽高是包括边框和内边距的,但不包括外边距。这时候我们可能会想到另一种获取宽高的方式。就是用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系列的属性只能获取到元素的属性,而不能更改用他来更改元素的属性。

  下面再来看看offsetLeftoffsetTop;首先来看看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是当前盒子的外边框距离定位的父盒子的内边框的距离,如果父级元素没有定位的话,默认是以文档的左侧为准。而如果父盒子有定位,则是当前盒子的外边框到定位的父盒子的内边框的距离。offsetTopoffsetLeft的属性相同,只不过他是相对于父盒子上内边距的距离或者文档的上方为准。

原文地址:https://www.cnblogs.com/wqc5730/p/5769264.html