BOM 浏览器对象模型与window常见事件对象
在白龙网看来,浏览器对象模型,他是与浏览器窗口进行交互的对象,由相关的对象组成,并且每个对象提供了很多方法、属性。JS标准是由ECMA提供,DOM标准由W3C提供,BOM标签是由netscap提供,缺乏标准。
BOM比DOM大,它的最高对象是window,包含:document、location、navigation、screen、history.
window对象是浏览器的顶级对象,它具有双重角色:
A.它是JS访问浏览器的一个窗口;
B.它是一个全局对象,定义在全局作用域上的变量、函数都会变成window对象的属性和方法。
另外,widnow下的一个特殊属性:window.name
一、window常见事件
1、加载页面事件
传统的注册事件的方式,只能放在元素的后面才能生效;而使用window.load、DOMContentLoaded则可以放在任何地方让JS成功执行。
<body>
<script>
//load页面加载:等页面全部内容加载完毕,再执行JS
window.addEventListener('load',function() {
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
alert('方法1:传统方式注册事件-只能放在元素后面');
})
})
// 或者
window.onload = function() {
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
alert('方法2:传统方式注册事件-只能放在元素后面');
})
}
//2.DOMContentLoaded,等DOM加载完毕就执行JS,不用等CSS/FLASH等等加载完,执行速度快些
window.addEventListener('DOMContentLoaded',function() {
var btn = document.querySelector('button');
btn.addEventListener('click',function() {
alert('DOM加载完毕,执行JS');
})
})
</script>
<button>按钮</button>
</body>
2、窗口大小事件
<body>
<style>
div {
width: 200px;
height: 200px;
background-color: red;
}
</style>
<script>
//1.方式1:传统方式onresize改变窗口大小,就化触发事件
// window.onresize = function() {
// console.log('变化了');
// }
//2.方式2:触发窗口大小事件resize
window.addEventListener('load',function() {//在任意位置加载页面
var div = document.querySelector('div');
window.addEventListener('resize',function() {
console.log(window.innerWidth);
if (window.innerWidth <= 800) {//获取窗口宽度
console.log('大小');
div.style.display = 'none';
} else {
div.style.display = 'block';
}
})
})
</script>
<div></div>
</body>
二、window常用对象
1、定时器对象
(1)setTimeout()
①基本语法
<script>
//1.setTimeout是window的一个对象,因此可以活力掉window
setTimeout(function() {
console.log('爆炸了');
}, 3000);
//2.函数可以写在setTimeout对象之内,也可以写在setTimeout对象之外(用函数名调用即可)
function callback() {
console.log('5秒之后就显示出来了');
}
//3.setTimeout的第二个参数是倒计时,单位是毫秒,默认省略时,为0,即没有倒计时
setTimeout(callback, 5000);
//4.用字符串的形式调用:'函数名()',不提倡这种方式
setTimeout('callback()', 6000);
//5.给不同的定时器起不同的标识符(名子)
var time1 = setTimeout('callback()', 6000);
</script>
②回调函数--广告在5秒之后消失(隐藏)
setTimeout(fn,time)与之前学过的element.onclick = function() {}、element.addEventListen('click',fn() {})中,提到的fn,都是回调函数,即:等某些事干完之后,再执行这个函数。
<body>
<img src="./close.png" alt="">
<script>
var img = document.querySelector('img');
setTimeout(function() {
img.style.display = 'none';
}, 5000);
</script>
</body>
③停止定时器
关闭定时器需要两步,一是给定时器标记一个ID,二是使用clearTimeout(定时器ID )。
<body>
<button>关闭定时器</button>
<img src="./close.png" alt="">
<script>
var btn = document.querySelector('button');
//1.给定时器标记一个ID
var img = document.querySelector('img');
var timer = setTimeout(function() {
img.style.display = 'none';
}, 5000);
btn.addEventListener('click',function() {
//2.通过一个点击事件,关闭定时器
clearTimeout(timer);
});
</script>
</body>
(2)setInterval()
①重复调用回调函数
<script>
//1.每间隔多长时间调用一次回调函数,即:重复调用回调函数;setTimeout只调用一次就结束
setInterval(function() {
console.log('123');
}, 2000);
</script>
②案例1:倒计时
<body>
<style>
span {
display: inline-block;
width: 20px;
height: 20px;
background-color: #999;
text-align: center;
line-height: 20px;
}
</style>
<span class="hour"></span>
<span class="minite"></span>
<span class="second"></span>
<button class="begin">开始</button>
<button class="stop">停止</button>
<script>
//1.获取元素
var hour = document.querySelector('.hour');
var minite = document.querySelector('.minite');
var second = document.querySelector('.second');
var inputTime = +new Date('2022-7-23 17:38:21');//计算停止时间
//2.计算时、分、秒,把计算得到的时、分、秒分别赋值给三个盒子
function getCountDown() {
var nowTime = +new Date();//计算当前时间
var times = (inputTime - nowTime) / 1000;//转换为秒
var h = parseInt(times / 60 / 60 % 24);//时
h = h < 10 ? '0' + h : h;
hour.innerHTML = h;
var m = parseInt(times / 60 % 60);//分
m = m < 10 ? '0' + m : m;
minite.innerHTML = m;
var s = parseInt(times % 60);//秒
s = s < 10 ? '0' + s : s;
second.innerHTML = s;
}
//3.每间隔1秒调用一次回调函数,实现倒计时功能
getCountDown();//调用时分秒函数的目的是在刷新时不显示空白
//4-1获取开始、停止按钮
var begin = document.querySelector('.begin');
var stop = document.querySelector('.stop');
//4-2定义一个定时器的全局变量,用来关闭定时器
var timer = null;
begin.addEventListener('click',function() {
//4-3点击开始,定时器开始工作
timer = setInterval(getCountDown,1000);
})
stop.addEventListener('click',function() {
//4-4点击结束,定时器停止工作:clearInnerval('定时器标识符')
clearInterval(timer);
})
//4.
</script>
</body>
③案例2:发送短信
<body>
<input type="number" name="" id="">
<button>发送</button>
<script>
//1.获取元素
var btn = document.querySelector('button');
var time = 5;
var timer = null;
//2.添加点击事件
btn.addEventListener('click',function() {
btn.disabled = true;
timer = setInterval(function() {
if (time == 0){
//3.如果定时器为0时,要停止定时器、恢复按钮状态/文字显示,同时要恢复倒计时的时间
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '发送';
time = 5;
} else {
//4.如果定时器不为0,就把按钮文字修改成倒计时内容,同时让变量执行--操作
btn.innerHTML = '剩下等待时间' + time + '秒';
time--;
}
}, 1000);
})
</script>
</body>
2、location对象
(1)获取设置窗口URL,并解析URL。location.href
<body>
<button>按钮</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function() {
//1.获取当前窗口的参数,直接写location.href
console.log(location.href);
//2.给location.href赋值,就可以跳转至新的页面
location.href = 'https://www.bailong.org.cn';
})
</script>
</body>
案例1:5秒之后自动跳转至新的页面
<body>
<div></div>
<script>
var div = document.querySelector('div');
var time = 5;
setInterval(function() {
if (time == 0) {
location.href = 'https://www.bailong.org.cn';
} else {
div.innerHTML = '你将在' + time + '秒之内进入新的网站';
time--;
}
}, 1000);
</script>
</body>
(2)获取URL参数,在不同页面传递参数 location.search
<body>
//1.action用来放置跳转的目标页面
<form action="plus.html">
//2.name必须写名称,用来接收传递的参数
<input type="text" name="uname">
<input type="submit" value="提交">
</form>
</body>
plus.html页面的布局与JS:
<body>
<div></div>
<script>
//1.获取参数
console.log(location.search);
//2.截取目标参数
var params = location.search.substr(1);
console.log(params);
//3.把字符串转换为数组
var arr = params.split('=');
console.log(arr);
//4.从数据中提取目标参数,并赋值给div标签
var div = document.querySelector('div');
div.innerHTML = arr[1] + '欢迎你';
</script>
</body>
(3)location其它属性
<script>
console.log(location.href);
console.log(location.protocol);
console.log(location.hostname);
console.log(location.port);
console.log(location.pathname);
console.log(location.hash);
console.log(location.search);
</script>
(4)location常用方法
<script>
setTimeout(function() {
//1.重定向,可以回退,类似于.href
location.assign('http://www.bailong.org.cn');
//2.替换页,实现跳转,不能回退
location.replace('http://www.bailong.org.cn');
//3.加载页面,没有参数类似F5刷新,参数为true,类似强制刷新
location.reload(true);
}, 1000);
</script>
3、navigator对象
<script>
//打印浏览器相关信息
console.log(navigator.userAgent);
</script>
4、history对象
与浏览器历史记录交互的对象,它包含用户访问过的URL。
<body>
<a href="https://www.bailong.org.cn">白龙网</a>
<button>前进</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function() {
//1.前进一步
history.forward();
//2.后退一步
history.back();
//3.前进与后退一步
history.go(1);
history.go(-1)
})
</script>
</body>
三、JS运行机制
(1)this指代问题
this,一般情况下,指向的是调用它的那个对象。例如,在全局变量、普通函数、定时器、对象中的方法中this指代的window;而在事件中this指代的是调用他的元素;在构造函数中this指代的是调用它的构造函数。
<body>
<button>按钮</button>
<script>
//1.全局变量下this指代widow
console.log(this);
//2.普通函数下this,函数要调用才能生效指代widow
function fn() {
console.log(this);
}
fn();
//3.定时器函数中的this指代widow
setTimeout(function() {
console.log(this);
}, 1000);
//4.对象中方法的this指代widow
var bailong = {
sayHai: function() {
console.log(this);
}
}
bailong.sayHai();
//5.事件中上的方法this指代btn
var btn = document.querySelector('button');
btn.onclick = function() {
console.log(this);
}
btn.addEventListener('click',function() {
console.log(this);
})
//6.构造函数中的this指代构造函数Fn,函数与构造函数都是先声明,再调用才能生效
function Fn() {
console.log(this);
}
var bailong = new Fn();
</script>
</body>
(2)JS执行机制
①JS是单线程
即同一时间就做一件事。这意味着,只有前面一件事做完,才能做后面的事。如果前面执行时间过长,就会导致渲染页面加载时受到阻塞。
为了解决这个问题,可以使用同步与异步的做法。同步,就是前一个事儿做完之后,再做另外一件事。异常,在前一件事结束前,同时做另外的事,只不过另外的事与前一件事同时结束。
②常规执行过程
同步任务都在主线程上执行,形成一个执行栈。JS异步放在任务队列之中,是通过回调函数实现的,主要包括3种:普通事件(click/resize)、资源加载(load/error)、定时器(setTimeout/setInnerval)。
首先,执行执行栈中的同步任务;
其次,把异步任务放到任务队列中;
最后,同步任务执行完毕,到任务队列中找没有执行的异常任务,把它放入执行栈中执行。
③有异步任务的执行过程
如果有事件、定时器、页面加载等异步任务,那么执行过程如下:
首先执行同步栈中的任务;
然后发现异步任务,提交给异步处理进程,如果触发了事件,就把事件放入异步栈;如果定时器时间到了,就把定时器放放任务队列……
最后,同步任务执行结束后,到任务队列中检查,有任务就把任务放到执行栈去执行,执行栈与任务队列循环的过程,叫事件循环。