4 JS执行机制
4.1 JS是单线程的
问题1引入
原先的JS是一个单线程的
<body>
<script>
//第一个问题
console.log(1);
setTimeout(function(){
console.log(3);
},1000);
console.log(2);//过去JS是单线程的,必须等待3打印之后,才会打印2;这是不合理的
</script>
</body>
4.2 异步和同步
上述4.2节的打印结果是:123;因为现在的JS允许异步
问题2引入
<script>
//第二个问题
console.log(1);
setTimeout(function() {
console.log(3);
}, 0);
console.log(2);
//打印结果123,求原因
</script>
1. 同步任务
同步任务是在主线程上执行,形成一个执行栈(同步任务放在执行栈中)
2. 异步任务
JS的异步步长是通过回调函数实现的。一般而言,异步任务有以下三种类型:
- 普通事件,如click esize等
- 资源加载,如loaderror等
- 定时器,包括setIntervalsetTimeout等
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)
4.3 JS执行机制
所以第二个问题中打印的是123
举例
有多个异步任务,执行结果是什么呢?
分析如下:
- 先将所以的任务分为同步任务和异步任务
- 执行
console.log(1);//打印1
- 执行
document.onclick = fun
由于这是异步任务,所以这时会将这句话提交给异步进程进行处理,由异步进程来决定要不要写道任务队列里,只有点击了鼠标才将这里的回调函数写到异步队列里,假设此时没点击,那么这里的回调函数就不会在异步队列里出现。
- 执行
console.log(2);//打印2
- 执行
setTimeout(fn,3000);
这也是异步任务,所以也会被提交给异步进程进行处理,等待3秒时间到了,才会被写到异步队列里。
- 写进去之后等待所以的同步任务执行完毕后,会检查异步队列里有没有异步任务,发现了console.log(3);之后将该语句拿到执行栈中进行执行,打印3,之后任务队列就空了
- 若此时点击了鼠标,那么有关鼠标点击的回调函数就写入异步队列,同步任务结束之后还会看异步队列里有没有任务,如果有,则再拿过来执行,异步队列又被清空
- 不断地点击鼠标,回调函数就会又写道异步队列里。同步任务就算全部执行完了也会一直回来看异步队列里有没有新消息,如果有的话再拿过来执行。这个反复执行的过程被称为事件循环。
5 location对象
5.1 什么是location对象
5.2 URL
5.3 location常见属性
- 举例
<body>
<button>点击</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// console.log(location.href);//点击按钮得到当前页面的地址 完整的写法是window.location
location.href = 'http://www.itcast.cn';//点击按钮跳转到新的页面
})
</script>
</body>
案例:5秒钟之后自动跳转页面【不需要点击按钮】
<body>
<button>点击</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
// console.log(location.href);//点击按钮得到当前页面的地址 完整的写法是window.location
location.href = 'http://www.itcast.cn'; //点击按钮跳转到新的页面
})
var time = 5;
setInterval(function() {
if (time == 0) {
location.href = 'http://www.itcast.cn';
} else {
div.innerHTML = '您将在' + time + '秒钟之后跳转到首页';
time--;
}
}, 1000)
</script>
</body>
案例:获取URL参数数据
主要练习数据在不同页面中的传递
效果呈现
页面1:login.html
<body>
<!-- 将这个表单提交到index.html页面上 form默认是get提交-->
<form action="index.html">
<!-- 表单必须要有name才可以提交 -->
用户名:<input type="text" name='uname'>
<input type="submit" value="登陆">
</form>
</body>
页面2:index.html[与login处于同一个文件夹下]
<body>
<div></div>
<script>
console.log(location.search); //?uname=andy 【在login.html输入andy提交之后,页面跳转到index.html,在index.html页面会打印?uname=andy】
//1.先去掉'?' 用到:substr('起始位置',截取几个字符)
var params = location.search.substr(1); //从u开始截取,一直到末尾
console.log(params); //uname=andy
//2. 利用'='将字符串分割为数组 split('=')
var arr = params.split('=');
console.log(arr); // ["uname", "andy"]
//3. 把数据写入div
var div = document.querySelector('div');
div.innerHTML = arr[1] + '欢迎您';
</script>
</body>
5.4 location对象方法
<body>
<button>点击</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
//1. location.assign()可以记录浏览历史,实现后退功能
// location.assign('http://www.itcast.cn'); //点击按钮之后实现页面跳转
//2. location.replace()不记录浏览历史,不可以实现后退功能
// location.replace('http://www.itcast.cn');
//3. location.reload()重新刷新页面
location.reload(true);//参数为空或者为false,如加上参数true为强制刷新
})
</script>
</body>
6 navigator对象
- 实验:在一个PC端网页写上
<script>
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = "../H5/index.html"; //手机
}
</script>
之后在手机端打开可以实现跳转到../H5/index.html
7 history对象
- history实际开发中用的少,OA系统中较为常用
- 首页
<body>
<a href="list.html">点击我去往列表页</a>
<button>前进</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// history.forward();
history.go(1); //前进1步
});
</script>
</body>
- 列表页
<body>
<a href="index.html">点击我去往首页</a>
<button>后退</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
history.back();
history.go(-1); //后退1步
});
</script>
</body>