这里主要聊聊js是如何在Web浏览器中实现的,介绍一些常见的API以及使用方法
1.Window对象
Window对象是客户端js程序的全局对象,是所有客户端js特性和api的主要接入点(所以在js中用到window对象时this一般都会指向全局)
时间循环相关
-
setTimeout和setInterval
- 这两个API用来注册在指定时间之后单次或者重复调用的函数,前者是只调用一次,后者重复调用,声明时会生成一个id,如果不使用
clearTimeout(id)
和clearInterval(id)
,计时器就会一直保留,引起内存泄漏 setTimeout()
的执行间隔跟函数执行时间有关,以下面的函数为例,触发事件时先将onclick事件处理程序放入队列中,等到程序执行时才打开定时器,理论上200ms之后代码就会执行,但假设事件处理程序执行代码花了300ms,那代码的实际执行时间就会是300ms之后
btn.onClick = function(){ setTimeout(function(){ // DO something },200) }
-
setInterval()
的执行间隔与函数执行时间木有关系,设置了200ms就会老老实实的每隔200ms执行一次,才不会管上一次的执行状态是怎么样的。这样的话可能会导致定时器里的代码会连续运行,js引擎想到了一个方法进行解决,当使用setInterval()
时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。这确保了定时器代码加入到队列中的最小时间间隔为指定间隔。但是这样的话很明显又会引入新的问题,可能当中某次执行就会被跳过。// 可以通过链式调用setTimeout来模拟setInterval setTimeout(function fn(){ console.log('我被调用了'); setTimeout(fn, 100); },100);
- 这两个API用来注册在指定时间之后单次或者重复调用的函数,前者是只调用一次,后者重复调用,声明时会生成一个id,如果不使用
-
requestAminationFrame
- 这个API也是浏览器用于定时循环操作的一个接口,但是不像setTimeout这种人为的设置间隔时间,而是根据显示器的刷新频率(60Hz/75Hz)执行,进行页面重绘。此外,使用这个API,一旦页面不处于浏览器的当前标签,就会自动停止刷新,这样能节省CPU、GPU和电力
- 它可以传入一个callback,使得在这个时间间隔内可以重复执行一些操作,按照名字来看可以知道它主要是用来对动画的刷新和执行,和显示器刷新频率一起刷新动画的话,动画就会显得比较顺畅。
- raf是在主线程上完成的,这意味着如果主线程比较繁忙,它的动画效果就会被打折扣
-
requestIdleCallback
- 这个方法将在浏览器的空闲时段内调用的函数排队。这使得开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件。意思就是说它会在每次屏幕刷新时判断当前帧是否还有多余时间,如果有的话就会调用对应的回调函数
- 参数有俩:
callback
和options
,options有个timeout属性,如果指定这个属性并具有一个正值,并且尚未通过超时毫秒数调用回调,那么回调会在下一次空闲时期被强制执行 - 所以这个函数可以用来切割长任务,将任务切割成一小块一小块,当浏览器有空闲时间就会执行任务,如果当中有高优先级的任务就终止当前任务,等优先级高的任务出现再继续执行。React的fiber就是以这个API为基础实现的
界面跳转相关
在进行界面跳转的时候,有很多很多的方式,有时也会分不清情况,可能界面跳转是实现了,但是实际上会出现这样或者那样的问题,所以现在就记录一下经常使用的那些API
- window对象
(1)window.open(url, target, feature),target默认是_blank(打开新窗口),feature是一个用逗号分隔的项目列表,设置的是新窗口的一些属性
弊端:直接使用一般会被浏览器拦截,所以尽可能用别的方式(浏览器为了用户的安全着想,避免开发者乱用这个属性动不动就弹出来广告)
- location对象
location包含的是有关当前url的一些信息,包括:hash(锚),host(主机名+端口号),hostname(主机名),port(端口号),href(完整的路由),pathname(返回的url路径名),pretocol(协议),origin(协议+主机名+端口号),search(url的查询部分)等属性
href=origin + pathname
(1)location.reload():重新载入当前文档,相当于一个刷新的操作
(2)location.replace():用新的文档替换当前文档,因为是直接替换,所以history的后退是不可用的,替换之后没办法通过浏览器的后退按钮回去上一个文档界面
(3)location.assign():载入一个新的文档,因为文档是新的,所以可以通过回退返回到上一个文档界面
- history对象
history记录的是用户在浏览器窗口中访问过的url,实际上就是url的记录
(1)history.back():历史记录往上一页,类似于点击浏览器的(<—)
(2)history.forward():历史记录往下一页,类似于点击浏览器的(—>)
(3)history.go():任意跳到某个历史记录,0代表当前页,递减是往前,递增是往后
(4)history.pushState():向当前浏览器会话的历史堆栈中添加一个状态
(5)history.replaceState():替换当前浏览器的state对象,url栏会改变,但是不会主动刷新改变后的地址,也不会检查地址是否是正确的
2.Document对象
Document对象其实是属于window对象的一部分,每个载入浏览器的 HTML 文档都会成为 Document 对象。常用的API如下:
getElementById()
getElementByName()
getElementByTagName()
3.Element对象
element对象在HTML DOM中表示HTML对象,可以拥有类型为元素节点,文本节点,注释节点的子节点。常用的API如下:
appendChild()
removeChild()
insertBefore()
nextSibling()
setAttribute()
getAttribute()
getBoundingClientRect()
classList
有(add, remove,toggle三种方法,方法里写对应的类名)
常见的元素宽高对比:
- document.body.offsetWidth/offsetHeight:对象的可见宽高(包含border和margin)
- document.body.clientWidth/clientHeight:内容放入可见宽高(不包含border和margin)
- document.body.scrollWidth/scrollHeight:元素完整的宽高(包括被隐藏的部分)
- document.body.scrollTop/scrollLeft:滚动之后当前左上角的宽高(可修改来控制滚动)