JavaScript 获取窗口属性 dom尺寸
这部分知识属于查缺补漏,可以放松放松注意力,因为这块属于理解了就可以,然后把它封装到一个库里面以后用直接调就可以(面试没人问、考试也没人考)听懂了掌握了会封装方法,以后用的时候直接调就可以,
这块内容基本是一个概念,求屏幕尺寸的宽和高、求滚动条在哪里、求滚动条X轴和Y轴的坐标,都是边边角角的东西不是那么难
一、滚动条的滚动距离
window.pageXOffset/pageYOffset IE8及IE8以下不兼容
document.body/documentElement.scrollLeft/scrollTop 兼容性比较混乱,用时取两个值相加,因为不可能存在两个同时有值
封装兼容性方法,求滚动轮滚动距离getScrollOffset()
因为有兼容的问题,滚动条有很多种求的方法
1、3WC标准方法
PS:
IE9是一个非常尴尬的浏览器,IE9以上完全支持W3C标准,IE9以下没有支持W3C标准(部分不支持),IE9支持了一小点但是更多的是没支持,
拿IE9作为一个分界线,IE9以下没有特别好的遵循W3C标准,IE9以上支持了,IE9是一个过渡版本
这是window上的两个属性,这两个属性就是求滚动条滚动距离的,IE9以上的浏览器能用,IE8及IE8以下浏览器不兼容
window.pageYOffset 现在滚动条没滚动,返回的是0
把滚动条往下挪了一下,再调用 window.pageYOffset,返回的数值是527,数值单位是像素
问一个问题:
现在滚动条往下滚动了400像素,从 浏览器最顶端 到滚动条 滚动的位置 一共有多少个像素?
要400像素 + 首屏像素,因为滚动条滚动的距离就相对于多挪出来的距离
换句话应该这么说,滚动条滚动了400像素,此时屏幕的低端 距离 整个网页的最顶端 有多少像素?400像素 + 首屏像素 这是一个以后会经常求的问题
元素的宽度超过屏幕的宽度,肯定就有横向的滚动条了
<hr style="width:1000px;">
window.pageXOffset 挪动横向滚动条,返回数值225,是横向滚动条滚动的距离
2、IE8及IE8下用的方法
IE8及IE8以下浏览器支持两个方法
第一个
document.body.scrollLeft 横向滚动条的距离(和标准方法window.pageXOffset结果是一样的)
document.body.scrollTop 纵向滚动条的距离
第二个
document.documentElement.scrollLeft
document.documentElement.scrollTop( documentElement代表html )
这块有一个兼容性混乱的问题
document.body.scrollLeft/scrollTop方法能用
document.documentElement.scrollLeft/scrollTop方法就用不了
这两个方法到底在哪个浏览器上好用是没有定论的,
这两个方法有个规律是互相冲突,在任何一个浏览器上但凡 document.body.scrollLeft/Top有值,document.documentElement.scrollLeft/scrollTop 一定是0
所以它两最好的用法是相加
document.body.scrollLeft + document.documentElement.scrollLeft; document.body.scrollTop + document.documentElement.scrollTop;
求滚动条滚动的距离,明明一个方法就能搞定,由于兼容性出现了一大堆问题
3、封装一个兼容性 getScrollOffset() 方法
Offset 是尺寸的意思,求滚动条滚动的尺寸,
这个方法一旦调用,就能实时的返回当前滚动条的滚动距离,返回的 x, y 分别代表滚动条滚动的 x轴距离,y轴距离
function getScrollOffset(){ if(window.pageXOffset){ return { x : window.pageXOffset, y : window.pageYOffset } }else{ return{ x : document.body.scrollLeft + document.documentElement.scrollLeft, y : document.body.scrollTop + document.documentElement.scrollTop } } } // 再强调一下,写程序尽量符合Linuk写法 // function getScrollOffset(){ // if(window.pageXOffset){ // return { // 1. linuk写法就是,把大括号写到整个程序的后面(return {}后面)。 // x: window.pageXOffset, // y: window.pageYOffset // } // }else{ // return // 2. 不要这么写 // { // // 3. 其它情况也就罢了,但是在return的情况下,不按照linuk写法就return不回去对象了,return的是undefined空 // // 4. 因为系统会自动在每一句后面,不写分号会自动给加分号(return ;) // x: document.body.scrollLeft + document.documentElement.scrollLeft, // y: document.body.scrollTop + document.documentElement.scrollTop // } // } // }
测试用else下面的IE老方法
function getScrollOffset(){ if(0 && window.pageXOffset){ // 让上面这个失效用下面的 return { x: window.pageXOffset, y: window.pageYOffset } }else{ return{ x: document.body.scrollLeft + document.documentElement.scrollLeft, y: document.body.scrollTop + document.documentElement.scrollTop } } }
返回的结果
把封装完的方法放到一个代码库里面tools.js,想用这个库里面的方法时引入这个库
二、查看视口的尺寸
window.innerWidth/window.innerHeight (IE8及IE8以下不兼容)
document.documentElement.clientWidth/clientHeight (标准模式下,任意浏览器都兼容)
document.body.clientWidth/clientHeight (适用于怪异模式下的浏览器)
封装兼容性方法,返回浏览器视口尺寸getViewportOffset()
什么是可视区窗口?
可视区窗口就是我们编写html文档能看到的部分
1、3WC标准模型下视口尺寸
求可视区窗口的尺寸分为很多个方法,首先W3C标准的方法,IE8及IE8以下不兼容
window.innerWidth
window.innerHeight
如果用 ctrl+ 放大页面,页面的尺寸也会跟着一起拉伸,求的时候页面尺寸会变小,就像比如用放大镜看,视觉上挺大其实很小
2、IE8以及IE8以下的方法是两个形式
标准模式下
document.documentElement.clientWidth
document.documentElement.clientHeight
不标准模式也就是怪异模式下
document.body.clientWidth
document.body.clientHeight
HTML文档以上第一行 <!DOCTYPE html> 启到很重要的作用,
标准模式:加上<!DOCTYPE html>就变成了标准模式
非标准模式:<!DOCTYPE html>删了浏览器的渲染模式就变成了怪异模式
标准模式和怪异模式是干什么的呢?
历史的问题,IE6到IE7版本的提升,肯定是摒弃了一些之前的东西,然后新启了一些新的东西,所以两个浏览器的语法规则包括所容纳的一些规范肯定不一样,
如果2001年IE6诞生开发的网站完全符合IE6语法,几年后后IE7诞生了,大多数用户采用IE7浏览之前IE6时候写的网页会有冲突,
IE6时候写的部分语法代码是根据IE6来写的,现在用IE7来访问网站势必存在一些不兼容的问题,这些问题唯一解决的办法就是重写。
后来大家研究可不可以有一种模式,即使是IE7访问给IE6写的代码,它依然可以按照IE6的语法规则来渲染页面,
后来大家研究出一种规则,让浏览器除了“标准的渲染模式”以外还要有一种渲染模式叫“怪异模式”,怪异模式唯一一点用途就是向后兼容,意思是比如IE7启动"怪异模式"它符合的语法规则不在是IE7是IE6,
每一个浏览器都有两种渲染模式,一种是渲染模式叫"标准模式",另一种是叫"怪异模式"也叫混杂模式,
怪异模式一经启动它所识别的语法就不在是最新的语法,而是试图去兼容之前的语法,
但是也不用太纠结这个问题,谷歌浏览器的现在的和之前的差别几乎看不到,唯一怪异模式有那么一点用处的就是IE的那几个问题,一般情况下是不需要的。
<!DOCTYPE html> 删了就是混杂模式,出来就是标准模式
<!DOCTYPE html>叫文档类型也叫DTD,DTD分为很多种形式具体的后面再讲,现在这是html5形式的DTD也是最简化的之前的要写很长
IE8及IE8以下浏览器访问视口
document.documentElement.clientWidth 在标准模式下IE8及IE8以下浏览器访问视口尺寸用的方法(client是计算机标准用语"客户端"的意思)
document.documentElement.clientHeight
在怪异模式下采用方法,怪异模式和标准模式就差一个documentElement
document.body.clientWidth
document.body.clientHeight
封装兼容性方法之前考虑一个问题,基本分为两种情况,
一种是IE9以上,
一种是IE9以下,
但是IE9以下是"标准模式"还是"怪异模式"怎么判断?
3、compatMode属性
有一个属性是document上的compatMode属性(compat是兼容性的意思)
document.compatMode 返回CSS1Compat,说明是标准模式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>标准模式</title> </head> <body> <script> console.log(document.compatMode); // CSS1Compat </script> </body> </html>
把最上面的<!DOCTYPE html>删了,返回的是BackCompat
<!-- 注释掉<!DOCTYPE html> --> <html> <head> <meta charset="UTF-8"> <title>怪异模式</title> </head> <body> <script> console.log(document.compatMode); // BackCompat </script> </body> </html>
BackCompat就是向后兼容的意思,通过document.compatMode返回的文字来区分是什么模式
4、封装兼容性函数
封装getViewportOffset()方法( Viewport是可视区窗口的意思 )
function getViewportOffset(){ if(window.innerWidth){ return { w: window.innerWidth, h: window.innerHeight } }else{ if(document.compatMode === "BackCompat"){ return { w: document.body.clientWidth, h: document.body.clientHeight } }else{ return { w: document.documentElement.clientWidth, h: document.documentElement.clientHeight } } } } alert('w: ' + getViewportOffset().w + ' ' + 'h: ' + getViewportOffset().h);
强制用IE8及IE8以下的方法,会发现把滚动条占用的距离也计算进去了
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>视口尺寸</title> <style> div{width:10000px;height:10000px;} </style> </head> <body> <div style=""></div> <script> function getViewportOffset(){ if(0 && window.innerWidth){ // 强制走下面用IE8及IE8以下的方法 return { w: window.innerWidth, h: window.innerHeight } }else{ if(document.compatMode === "BackCompat"){ return { w: document.body.clientWidth, h: document.body.clientHeight } }else{ return { w: document.documentElement.clientWidth, h: document.documentElement.clientHeight } } } } alert('w: ' + getViewportOffset().w + ' ' + 'h: ' + getViewportOffset().h); </script> </body> </html>
滚动条三种方法求出宽度,W3C的标准方法window.innerWidth求出的是整个屏幕分辨率宽度1920,IE8及IE8以下的方法有点区别
三、查看元素的几何尺寸
domEle.getBoundingClientRect()
兼容性很好
该方法返回一个对象,对象里面有left, top, right, bottom等属性。
left和top代表该元素左上角的X和Y坐标,
right和bottom代表元素右下角的X和Y坐标
height和width属性老版本IE并未实现
返回的结果并不是“实时的”
getBoundingClientRect() 方法返回一个内容包,
内容包里面包含了这个元素所呈现宽高位置的一些信息,这个方法是任何DOM元素都可以调用的(Rect是方块的意思,square也是方块的意思,Rect是矩形square是正方形都是方块的意思)
<div style="width:100px;height:100px;background-color:orange;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; console.log(div.getBoundingClientRect()); // DOMRect {x: 100, y: 100, width: 100, height: 100, top: 100, …} /** * bottom: 200 bottom是下低,低边是200 * height: 100 height属性IE里面没有 * left: 100 * right: 200 * top: 100 * width: 100 width属性IE里面没有 * x: 100 * y: 100 */ </script>
div调用getBoundingClientRect()方法返回一个对象,这个对象包含了div元素的几乎一切信息
先看是一类
bottom:200
left:100
right:200
top:100
这四个方向是四个边的像素位置,换句话说求的是左上点 和 右下点的坐标
然后还有两个信息一个是width一个是height,也就是说这个div的宽高位置都能求出来,
这也是getBoundingClientRect()的特点可以返回这样一个包,它的兼容性是比较好的,里面包含6个属性中width、height这两个求尺寸非常重要的属性在IE里没有
IE浏览器通过这个方法求宽高
right - left = width 右侧边减左侧边求的是宽度
bottom - top = heigth 底边减去top求的是高度
<div style="width:100px;height:100px;background-color:orange;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; var box = div.getBoundingClientRect(); console.log("width: " + (box.right - box.left)); // width: 100 console.log("heigth: " + (box.bottom - box.top)); // heigth: 100 </script>
这个方法是es5的新方法,我们只作为了解就可以了,因为后期求元素尺寸的方法太多了,比这个方法好用的多的是
最后一点它返回的结果并不是实时的,它返回的是这个方块此时此刻静态的写照,什么是静态的?
<div style="width:100px;height:100px;background-color:orange;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; var box = div.getBoundingClientRect(); // 1. 变量box储存好这个结果,box是一个对象里面包含了很多数据, div.style.width = '200px'; // 2. div元素的宽改成200像素 console.log(box); // 3.DOMRect {x: 100, y: 100, width: 100, height: 100, top: 100, …} /* 现在依然访问box元素的值和刚才是一模一样的,width还是100、right还是100尺寸位置都没有变 bottom: 200 height: 100 left: 100 right: 200 right还是100 top: 100 width: 100 width还是100 x: 100 y: 100 __proto__: DOMRect */ console.log(div.getBoundingClientRect()); // 重新获取一次width变成200,相应的左边距right变成300 /* bottom: 200 height: 100 left: 100 right: 300 top: 100 width: 200 x: 100 y: 100 __proto__: DOMRect */ </script>
我们了解js里面提供了一个这样的方法就行了,只不过js里面提供了很多方法,方法和方法之间难免会有冲突,难免有一些方法会让另一些方法成为永久的不可能开启的方法了
四、查看元素的尺寸
dom.offsetWidth
dom.offsetHeight
dom.offsetWidth
dom.offsetHeight
这些方法就是让的 getBoundingClientRect() 成为永远报废的方法,这两个方法也是查看一个元素尺寸的,只不过这回查看元素尺寸方便多了
任何一个DOM元素都可以调用 dom.offsetWidth/offsetHeight,分别宽高返回100
<div style="width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; console.log(div.offsetWidth); // 100 console.log(div.offsetHeight); // 100 </script>
探究一下,
求出的width和heigth是实际内容区的宽高还是看起来视觉上的宽高?
div元素加100像素padding,现在再求div的宽高返回的是300像素
<div style="padding:100px;width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; console.log(div.offsetWidth); // 300 console.log(div.offsetHeight); // 300 </script>
就想求div元素内容区的宽高怎么求?用刚才的 getBoundingClientRect() 方法返回的也是300
<div style="padding:100px;width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; console.log(div.getBoundingClientRect()); // DOMRect {x: 100, y: 100, width: 300, height: 300, top: 100, …} </script>
这两个方法返回的都是div看起来的尺寸,既然两个方法的功能都一样,那offsetWidth就完全把getBoundingClientRect()给取代了
求div内容区宽高,需要后续的知识 div.style.height 这是间接的来访问CSS
<div style="padding:100px;width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; console.log(div.style.height); // 100px console.log(div.style.width); // 100px </script>
dom.offsetWidth
dom.offsetHeight
这两方法求的是元素视觉上的尺寸包含width、height、padding、border不包含margin
五、查看元素的位置
dom.offsetLeft, dom.offsetTop
对于无定位父级的元素,返回相对文档的坐标
对于有定位父级的元素,返回相对于最近的有定位的父级的坐标 ( 无论是 left 还是margin-left等,都是距离 )
dom.offsetParent 返回最近的有定位的父级,
如无,返回body,
body.offsetParent返回null
eg:求元素相对于文档的坐标。
作业,求元素相对于文档的坐标getElementPosition()
1、查看元素的位置有两个方法 dom.offsetLeft 和 dom.offsetTop
div的位置left和top值都返回了100,但是这两个方法没有想的那么理想
<div style="padding:100px;width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> <script> var div = document.getElementsByTagName('div')[0]; console.log(div.offsetLeft); // 100 console.log(div.offsetTop); // 100 </script>
现在把这个div放到另外一个大div里面
<div style="width:300px; height:300px; border:1px solid saddlebrown; position:relative;top:100px;left:100px;"> <div class="demo" style="width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> </div>
为什么里面的div会在外边的大div中间呢?
因为里面div设置的是 position:absolute、left:100、top:100,而绝对定位position:absolute是相对于它有定位的父级定位的,正好外面的大div有position:relative定位,所以里面的div在中间
下面求里面的小div在页面里的位置,其实它在页面里的位置应该是left:200、top:200,但是里面的小 div.offsetLeft 返回的是100像素,它求的不是相对于页面那个的位置,求是相对于父级的位置
<div style="width:300px; height:300px; border:1px solid saddlebrown; position:relative;top:100px;left:100px;"> <div class="demo" style="width:100px;height:100px;background-color:aqua;position:absolute;top:100px;left:100px;"></div> </div> <script> var div = document.getElementsByClassName('demo')[0]; // 用class选择器选择里面的div(里面的div加一个class="demo") console.log(div.offsetLeft); // 100 </script>
这块理解是,里面的div首先有定位,然后在相对应它父级的位置才是我们求的值,如果里面的小div没有定位呢?
如果里面的小div居中不是通过改变top、left,而是通过改变margin的这个方法还好用吗?下面返回的还是100
<div style="width:300px;height:300px;border:1px solid saddlebrown;position:relative;top:100px;left:100px;"> <div class="demo" style="width:100px;height:100px;background-color:aqua;position:absolute;margin-left:100px; margin-top:100px;"></div> </div> <script> var div = document.getElementsByClassName('demo')[0]; console.log(div.offsetLeft); // 返回的还是100 </script>
解释一下,
这个 offsetLeft 真正的含义是忽略自身是不是定位元素,它不管自身是不是定位元素,它求的只是这个元素距它有定位的父级的距离
不管这个距离是怎么生成的,是margin生成的还是定位生成的它都不管,但凡里面的小div和有定位的父级有距离就把这个距离的值反回来,
offsteLeft这个left指的不是定位的那个left,它求的就是横向上我和你的距离的left,表示的是一个方向不是语法,
但有一点,里面的小div关注的是外面的div是不是有定位的父级,如果是有定位的父级,那里面小div求的offsetLeft就是距离这个有定位父级的一个距离,如果外面的div不是有定位的父级,那求的就是距离外层边框。
总结:
对于无定位父级的元素,返回相对文档的坐标。
对于有定位父级的元素,返回相对于最近的有定位的父级的坐标(无论是left还是margin-left等都算距离)
试一下,把外面的大div父级也变成不是定位的,position的默认值是static(static是静态的)
<div style="width:300px;height:300px;border:1px solid saddlebrown;position:static;margin-left:100px;margin-top:100px;"> <div class="demo" style="width:100px;height:100px;background-color:aqua;position:absolute;margin-left:100px;margin-top:100px;"></div> </div> <script> var div = document.getElementsByClassName('demo')[0]; console.log(div.offsetLeft); // 209 = 边框1px + body里面默认的margin:8px console.log(div.offsetTop); // 201 = 边框1px + 父元素大div的margin-top:100px与body默认纵向的margin:8px它两重叠塌陷掉了 // PS: 横向的两个margin会相加,纵向的margin肯定会出塌陷的问题 </script>
2、dom.offsetParent
还有一个方法 dom.offsetParent 能把最近的有定位的父级求出来,现在里面的小div最近没有有定位的父级
<div style="width:300px;height:300px;border:1px solid saddlebrown;margin-left:100px;margin-top:100px;"> <div class="demo" style="width:100px;height:100px;background-color:aqua;position:absolute;margin-left:100px;margin-top:100px;"></div> </div> <script> var div = document.getElementsByClassName('demo')[0]; console.log(div.offsetParent); // 没有有定位的父级返回<body>...</body> console.log(div.offsetParent.offsetParent); // 最顶级就是body了,body.offsetParent没有返回null </script>
如果外面的大DIV有定位加上 position:relative 定位
<div style="width:300px;height:300px;border:1px solid saddlebrown;margin-left:100px;margin-top:100px;position:relative;"> <div class="demo" style="width:100px;height:100px;background-color:aqua;position:absolute;margin-left:100px;margin-top:100px;"></div> </div> <script> var div = document.getElementsByClassName('demo')[0]; console.log(div.offsetParent); // 返回的是外边的大div </script>
返回的是外边的大div
3、作业
求任意一个元素相对于文档的坐标,给一个元素不知道它有没有定位的父级,还不知道有多少位定位的父级。
思路是什么?
1 先看它有没有有定位的父级,如果有先求它距离有定位父级的距离。
2 然后在把视角换在它有定位的父级上,看看它父级上面还有没有有定位的父级。
3 一段一段的加一直加到最后,这是一个循环递归的过程
函数名叫getElementPosition()
六、让滚动条滚动
window上有三个方法
scroll(), scrollTo(), scrollBy();
三个方法功能类似,用法都是将x,y坐标传入。即实现让滚动轮滚动到当前位置。
区别:scrollBy()会在之前的数据基础之上做累加。
eg:利用scrollBy()快速阅读的功能
之前是获取信息,
1. 滚动条滚动的距离
2. 窗口尺寸
3. 元素尺寸/距离
让滚动条滚动,这节是操作,
window上有三个方法scroll()、scrollTo()、scrollBy()
其实这三个方法就两个方法,前边这两个方法scroll() 和 scrollTo() 实现的是一样的用那个都行
1、scroll() 和 scrollTo() 两个方法是一样的
window.scroll(x, y) 能让滚动条滚动,里面填写两个参数,
参数一,让x滚动轴滚动距离
参数二,让y轴滚动条滚动距离
window.scroll(0 ,100) 第一个x轴没有填0,第二个填100,执行就会走到滚动条滚动到100的位置
再执行一次不动,再执行一次还不动…说明什么?
说明让滚动条滚动到当前位置,而不是累计滚动到当前距离。
window.scroll 和 window.scrollTo 没有任何差别是一样的,
window.scrollTo(0 ,100) 执行滚动到100的位置,反复执行也是一样的,兼容性都是一样的,不知道为什么出两个方法!
2、scrollBy()
第三个方法 scrollBy() 和上面两个方法不一样, window.scrollBy(0, 10) 第一个参数也是x轴距离,第二个参数是y轴距离,但是scrollBy是累加滚动距离
window.scrollBy(0, 10) 执行会向下滚动10个像素
再执行再执行再执行…就一直会往下累加
scrollBy不是滚动多少个点,是还要往下滚动多少个距离。
写负-10滚动上去了 window.scrollBy(0, -10);
通过动态改变滚动条,这样累加滚动可以调整页面的滚动
3、作业
利用scrollBy()快速阅读的功能,点击start滚动,点击stop停止滚动
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>小例子,自动阅读</title> <style> body{margin:0; height:10000px;} </style> </head> <body> <div style="height:60px;width:60px;position:fixed;bottom:130px;right:30px;background:#eee;text-align:center;line-height:60px;cursor:pointer;opacity:0.9;">Stop</div> <div style="height:60px;width:60px;position:fixed;bottom:200px;right:30px;background:#eee;text-align:center;line-height:60px;cursor:pointer;opacity:0.9;">Start</div> <script> var stop = document.getElementsByTagName('div')[0], start = document.getElementsByTagName('div')[1], timer = 0; start.onclick = function(){ // 点击开始自动阅读 timer = setInterval(function(){ window.scrollBy(0, 10); },100); } stop.onclick = function(){ // 点击停止定时器 clearInterval(timer); } </script> </body> </html>
但是有一个问题,多次点击start会加速,因为产生了多个定时器,点击stop停不了
解决方法加一个锁
var stop = document.getElementsByTagName('div')[0], start = document.getElementsByTagName('div')[1], timer = 0, key = true; // 加一个开关,一开始是true start.onclick = function(){ if(key){ timer = setInterval(function(){ window.scrollBy(0, 10); // window.scrollBy(0, num); 加速调节num,单独设置一个按键给num加 },100); key = false; // 1. 开启定时间后把锁关上 console.log(key); } } stop.onclick = function(){ clearInterval(timer); key = true; // 点击stop时把锁在打开 console.log(key); }