JavaScript Window(BOM 对象)

浏览器对象模型 (BOM)

http://www.w3school.com.cn/js/js_window.asp

https://developer.mozilla.org/zh-CN/docs/Web/API/Window

浏览器对象模型(Browser Object Model)尚无正式标准。由于现代浏览器已经(几乎)实现了 JavaScript 交互性方面的相同方法和属性,因此常被认为是 BOM 的方法和属性。

所谓的浏览器对象模型,指的是把整个浏览器看做一个对象。  (该对象就是window),通过修改window对象的属性来修改浏览器的设置,通过调用window对象的方法,来控制浏览器的行为,即面向window编程,但实际上操作的是浏览器( 这是面向对象编程思想最标准的体现 )
window对象是什么?
是javascript编程语言的最核心对象,有了它才能跟浏览器进行交互。也叫全局对象,即所有定义在全局范围的变量和函数,都属于window对象的一部分。全局变量(即定义变量时前 不加var),实际上是window的属性
window对象的结构

 

window对象的原理

var global = {
     Math : function(){...},
     Date : function(){...},
     doucment : {...},
     alert : function(){...},
     console : {...},
     window : this
}
window.location 只读属性,返回一个 Location  对象,其中包含有关文档当前位置的信息。
虽然其是个只读属性,但仍然可以赋给它一个 DOMString
window.location = 'http://www.example.com'
// 同下
window.location.href = 'http://www.example.com'

API:

reload(Boolean) // 刷新当前页面,可以传递参数,true表示强制从服务器重新加载当前页面,默认为false,即使用缓存
replace('http://www.cnblogs.com/fanlinqiang')// 修改地址并保持hash值
href // 当前页地址
hostname  //返回 web 主机的域名
pathname //返回当前页面的路径和文件名
port //返回 web 主机的端口 (80 或 443)
search //向服务器发送字符串数据
hash // #.., 地址中的hash值,在单页面应用中经常用到

navigator对象 (以下属性不兼容)

appName  //浏览器名称
appVersion  //浏览器版本
platform //操作系统
// 最新的浏览器已经全面放弃以上这些属性
userAgent  //用户代理信息,通过该属性可以获取浏览器及操作系统信息

如何判断移动端手机浏览器版本?

window.onload = function() {
 
  var u = navigator.userAgent;

  if(u.indexOf('Android') > 一1 ||  u.indexOf('Linux') > -1) { //安卓手机

    alert("安卓手机");

  } else if(u.indexOf('iPhone') > 一1) { //苹果手机

    alert("苹果手机");

  } else if(u.indexOf('Windows Phone') > 一1) { //winphone手机                          alert("winphone 手机");

  }

}
View Code
浏览器信息
// 浏览器信息
let browser = {
    versions: function () {
        let u = window.navigator.userAgent;
        return {
            trident: u.indexOf('Trident') > -1, //IE内核
            presto: u.indexOf('Presto') > -1, //opera内核
            webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1, //火狐内核
            mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
            ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
            android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器
            iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1, //是否为iPhone或者安卓QQ浏览器
            iPad: u.indexOf('iPad') > -1, //是否为iPad
            webApp: u.indexOf('Safari') === -1, //是否为web应用程序,没有头部与底部
            weixin: u.indexOf('MicroMessenger') === -1 //是否为微信浏览器
        };
    }()
};

 

history对象

length // 当前域名下访问页面的个数
back() //回退 forward() //前进 go(-2) //跳转指定页面
// 以下为h5新增
pushState(state, title, url) // 会触发popstate事件
history.replaceState({page: 3}, "title 3", "?page=3") 
需要注意的是调用history.pushState()history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()

实例:阻止浏览器后退按钮?使浏览器后退按钮失效

window.onload = function() {
    window.onpopstate = function() {
      window.history.pushState('forward', null, '#');
      window.history.forward(1);
    }
    window.history.pushState('forward', null, '#'); //在IE中必须得有这两行
    window.history.forward(1);
}
View Code

常见方法

open(url) // 
close()
blur()
alert() //  阻塞式方法
confirm() //用户交互、有boolean返回值;是一个阻塞式的方法,alert()也是阻塞式方法
prompt() //接收用户的反馈信息,返回值是字符串

 其中:let windowObjectReference = window.open(strUrlstrWindowName, [strWindowFeatures]);

strUrl === 要在新打开的窗口中加载的URL。

strWindowName === 新窗口的名称。

strWindowFeatures === 一个可选参数,列出新窗口的特征(大小,位置,滚动条等)作为一个DOMString

eval()方法     动态的执行代码,

1、将字符串解析为可执行的JavaScript语句
2、可以将字符串(符合对象格式的)转化为对象类型
//eval方法赋予了JS动态执行代码的能力,让它变成了一个名副其实 的灵活的语言(使用风险较大,已逐渐被淘汰)
function test() {
    var m = 'abc';
    eval('alert(m)');  //abc
}
// 将字符串转为对象时需要添加一层 {}
var a = '{name:123,age:456}'
console.log( eval("{a}") )

  setInterval 与 setTimeout 

JavaScript是单线程的语言,但使用setTimout(延时器) 和 setInterval(定时器)可以模拟多线程

setInterval(function(){
  console.log(111)
},1000)
setTimeout(function(){
  console.log(222)
},1000)

在JavaScript代码执行期间,遇到setTimeout 和 setInterval 会将其依次放置到执行栈中,当其他代码执行完后才开始执行执行栈中的“任务”,因此当碰到

... ...
setTimeout(function(){}, 0)
... ...

相当于将其中的任务放置到JavaScript代码最后执行,(1)如果回调的执行时间大于间隔间隔,那么浏览器会继续执行它们,导致真正的间隔时间 比原来的大一点;(2)它们存在一个最小的时钟间隔,在 IE6~IE8 中为 15.6ms6,后来精准到 10ms,IE10 为 4ms,其他浏览器相仿。但这些太容易受外部因素影响,比如电池快没电 了,同时打开的应用程序太多了,导致 CPU 忙碌,这些都会让它的数值偏高。

此外还有使用setInterval时其中的“任务”也是一个费时的过程则表现出的现象并不是我们想要的,如:假设我们想要一个任务每隔10s运行一次,而这个任务每次运行可能需要9秒,这样表现出来的可能就是每一秒就运行了这个任务;更有甚者,假设我们想要一个任务每隔10s运行一次,而这个任务每次运行的过程可能要11秒或者20s...,,这时候setInterval就会在执行栈进行累积,随后连续触发,为此我们可以使用setTimeout来实现我们想要的结果:

使用setTimeout代替setInterval??

!function(){
    console.log("这是一个需要9秒的任务")
    setTimeout(arguments.callee,10000)
}()

 面试题:

for(var i=0;i<3;i++){
    setTimeout(function(){
        console.log(i--) // 3 2 1
    },0)
} 

旧版本 IE 的最短时钟间隔太长,可利用 image 死链时立即执行 onerror 回调的情况来实现setTimeout

var orig_setTimeout = window.setTimeout;
window.setTimeout = function(fun, wait) {
    if (wait < 15) {
        orig_setTimeout(fun, wait);
    } else {
        var img = new Image();
        img.onload = img.onerror = function() {
            fun();
        };
        img.src = "data:,foo";
    }
}; 

JS是单线程还是多线程?

浏览器都是单线程的, 所有的代码执行都是同步
 
当有多个定时器出现时, 会交叉生成任务,存入浏览器的任务执行队列当中
setInterval(function(){console.log(1111);},0);
console.log(2222);
 
输出顺序:
   2222
   1111

 JavaScript引擎的主线程负责执行代码,由于只有一个线程,执行当然是同步的,即按顺序来。JavaScript中的异步通常都是通过回调函数来实现的,回调函数就是将函数的执行权转让给别人。另外,还有一个叫任务队列的东西,所有的异步代码都是从队列当中来。

所以在实际上我们会发现,JavaScript根本不能同时执行两个任务,本质上还是单线程。在JavaScript中所谓的异步有三种:

  1. 鼠标键盘事件触发,例如:onclick,onkeydown等等
  2. 网络事件触发,例如:onload,onerror
  3. 定时器,例如:setTimeout,setInterval

 

 

 

 

posted @ 2017-10-27 08:46  fanlinqiang  阅读(245)  评论(0)    收藏  举报