zoukankan      html  css  js  c++  java
  • 第8章 浏览器对象模型BOM 8.1 window对象

          ECMAScript是javascript的核心,但如果要在web中使用javascript,那么BOM(浏览器对象模型)则无疑是真正的核心。BOM提供了很多对象,用于访问浏览器的功能,在浏览器之间共有的对象渐渐成为了事实上的标准。W3C为了把浏览器中javascript最基本的部分标准化,已经将BOM的主要方面纳入了html5的规范中。

    Window对象

    @#BOM的核心对象是window,它表示浏览器的一个实例。在浏览器中,window对象有双重角色,它既是通过javascript访问浏览器窗口的一个接口,又是ECMAScript规定的global对象。这意味着在网页中定义的任何一个对象、变量和函数,都以window作为其global对象,因此有权访问parseInt()等方法。

    由于window对象同时扮演这ECMAScript中的global对象角色,因此所有全局作用域中声明的变量、函数都会变成window对象的属性和方法。举例如下:

      var age = 29;

      function sayAge(){

         alert(this.age);

      }

      alert(window.age);//29

      sayAge();//29

      window.sayAge();//29

    这里在全局作用域中的定义,他们被自动归在window对象名下。由于sayAge()存在于全局作用域中,因此this.age会被映射到window.age。

    其实定义全局变量与在window对象上直接定义属性还是有一点差别:    

          @#全局变量不能通过delete操作符删除,而直接在window对象上定义的属性可以。举例如下:

      var age = 29;

      window.color = "red";

      delete window.age;//在ie<9时抛出错误,在其他浏览器则返回false;

      alert(window.age);//29

      delete window.color;//在ie<9时抛出错误,在其他浏览器会返回true;

      alert(window.color);//undefined

    使用var语句添加的window属性有一个名为[configurable]的特性,这个特性的值被设置为false,因此这样定义的属性不可以通过delete操作符删除。Ie8级更早的版本在遇到使用delete删除window属性的语句时,不管该属性最初是如何创建的,都会抛出错误,以示警告。

          @#尝试访问未声明的变量会抛出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在。举例如下:

       var newValue  = oldValue;//这里会抛出错误,因为oldValue未定义

       var newValue  = window.oldValue; //这里不会抛出错误因为是一次属性查询,但是newValue为undefined

    窗口关系及框架

    如果页面中包含框架,则每个框架拥有自己的window对象,并且保存在frames集合中。在frames集合中,可以通过所以(从0开始,从左到右,从上到下)或者框架名称来访问相应的window对象。每个window对象都有一个name属性,其中包含框架的名称。

     <frameset rows="160,*">

       <frame src="top.html" name="top">

       <frameset cols="50%,50%">

          <frame src="left.html" name="left">

           <frame src="right.html" name="right">

       </frameset>

    </frameset>

    这里可以通过window.frames[0]或者window.frames[“top”]来引用上方的框架。

    但是最好使用top来代替window,因为top对象始终指向最外层框架,也就是浏览器窗口。使用它可以确保在一个框架中正确的访问另一个框架。而对于在一个框架中编写的任何代码来说,其中的window对象指向的都是那个框架的特定实例,而非最外层框架。

    与top相对的另一个window对象是parent。其始终指向当前框架的直接上层框,在没有框架的情况下,等同于top,此时它们都等于window

    在使用框架的情况下,浏览器中会存在多个global对象。在每个框架中定义的全局变量会自动成为框架中Window对象的属性。由于每个window对象都包含原生类型的构造函数,因此每个框架都有一套自己的构造函数,这些构造函数一一对应,但并不相等。如top.Object不等于top.frames[0].Object。这个问题会影响到对跨框架传递的对象使用instanceof操作符。

    窗口位置

    Ie,safari,opera,chrome提供了screenLeft和screenRight属性,分别表示窗口相对于屏幕左边和上边的位置。Firefox则提供的screenX和screenY属性,但与上面两个属性并不对应。示例:

    var leftPos = (typeof window.screenLeft =="number")?window.screenLeft:window.screenX;

    var topPos = (typeof window.screenTop =="number")?window.screenTop:window.screenY;

    这个例子用二元操作符首先确定screenLeft 和screenTop 属性是否存在,存在则取得这两个属性的值否则screenX和screenY的值。从而做到浏览器兼容。但是无法在跨浏览器的条件下取得窗口左边和上边的精确坐标值。

    使用moveTo()和moveBy方法可以将窗口精确地移到一个新位置。这两个方法都接收两个参数,moveTo(x,y)接收新位置的坐标值,moveBy(m,n)接收的是在水平和垂直方向上移到的像数。但是这两个方法可能被浏览器禁用,且不适用于框架,只能对最外层的window对象使用。

    窗口大小

    跨浏览器确定窗口大小并不是很容易。各种浏览器均提供了4个属性:innerWidth,innerHeight,outerWidth,outerHeight,但是其返回值并不一致,而且在ie6中,这些属性必须在标准模式下才有效,在混杂模式下,必须通过document.body.clientWidth取得信息。

    虽然最终无法确定浏览器窗口的大小,但是可以取得页面视口的大小:

      var pageWidth = window.innnerWidth;

      var pageHeight = window.innerHeight;

      if(typeof pageWidth != "number"){

        if(document.compatMode == "CSS1Compat"){

           pageWidth = document.documentElement.clientWidth;

           pageHeight = document.documentElement.clientHeight;

        }else{

           pageWidth = document.body.clientWidth;

           pageHeight = document.body.clientHeight;

        }

      }

    对于移动设备,window.innerWidth和window.innerHeigeht保存着可见视口,也就是屏幕上可见页面区域的大小。移动ie浏览器不支持这些属性,但通过document.documentElement.clientWidth及

    document.documentElement.clientHeight提供了相同的信息,随着页面的缩放,这些值也会相应变化。

    在其他移动浏览器中document.documentElement度量的上布局视口,即渲染后页面的实际大小(与可见视口不同,可见视口只是整个页面中的一小部分)。移动ie浏览器把布局视口的信息保存在document.body.clientWidth和document.body.clientHeight中,这些值不会随着页面缩放变化。

    使用resizeTo(x,y)和resizeBy(x,y)方法可以调整浏览器窗口的大小。其中resizeTo()接收浏览器窗口的新宽度和新高度,而resizeBy()接收新窗口与原窗口的宽度和高度之差。但是同样,这样两个方法可能被浏览器禁用,同时不适用于框架只能对最外层的window对象使用。

    Window.open

    Window.open()方法既可以导航到一个特定的URL,也可以打开一个新的浏览器窗口。

    方法的4个参数分别为:1.要加载的URL;2.窗口目标;3.一个特性字符串;4一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。通常只须传第一个参数,最后一个参数只在不打开新窗口的情况下使用。

    如果为window.open()传递第二个参数,而且该参数是已有窗口或框架的名称,那么就会在具有该名称的窗口或框架中加载第一个参数指定的URL。

    如果给window.open()传递的第二个参数并不是一个已经存在的窗口或框架,那么会根据第三个参数传入的字符串创建一个新窗口或新标签页。

    如果没有传入第三个参数,则会打开一个带有全部默认设置的新浏览器窗口。

    在不打开新窗口的情况下,会忽略第三个参数。

    第三个参数是一个逗号分隔的设置字符串(特性字符串中不允许出现空格),表示在新窗口中都显示哪些特性。

    Window.open()会返回一个指向新窗口的引用。通过返回对象,可以操作新打开的窗口。

    var testWindow = window.open("url");

      testWindow.resizeTo(500,500);

      testWindow.close();

    弹出窗口关闭之后,窗口的引用仍然还在,但只能检测其closed属性。testWindow .closed;//true

    新创建的window对象有一个opener对象,其中保存着打开它的原始窗口对象。这个属性只在弹出窗口的最外层window对象(top)中有定义,指向调用window.open()的窗口或框架。

    testWindow.opener = null;

    将openner属性设置为null就是告诉浏览器新创建的标签页不需要与打开它的标签页进行通信,因此可以运行在独立的进程中。标签页之间的联系一旦切断,将无法恢复。

    setTimeout()与setInterval()

    Javascript是单线程语言,但它允许通过设置超时值和间歇时间值来调度代码在特定的时间段运行。

    超时值调用即setTimeout()接收两个参数,第一个参数可以是一个包含js代码的字符串(与eval()函数中使用字符创一样),也可以是函数,第二个参数是一个表示等待多长时间的毫秒数。

    但是经过给定的时间后代码不一定执行,因为javascript是一个单线程序的解释器,因此一段时间内只能执行一段代码。,为了控制要执行的代码,就有一个javascript任务队列。这些任务会按照将它们添加到队列的顺序执行。setTimeout的第二个参数是告诉jsvascript再过多长时间将当前任务添加到队列中。

    setTimeout()会返回一个数值ID,计划执行代码的唯一标识符,可以通过它来取消超时调用。在指定时间结束之前调用clearTimeout(timeoutId),即取消超时调用。(超时调用的代码都是在全局作用域中执行的)

    类似的间歇调用setInterval(),会按照指定的时间间隔重复执行代码,直至间歇调用被取消或页面被卸载。

    参数也与setTimeout()一样,

    下面看一个经典示例:

      var num = 0;

      var max = 10;

      var intervalId = null;

      function incrementNumber(){

        num++;

        //如果执行次数达到了max设定值,则取消后续尚未执行的调用。

        if(num==max){

          clearInterval(intervalId);

          alert("done");

        }

      }

     intervalId = setInterval(incrementNumber,500);

    -----------------------------------------------------------------------

      var num = 0;

      var max = 10;

      var intervalId = null;

      function incrementNumber(){

        num++;

        //如果执行次数尚未达到max设定值,则设置另一次超时调用

        if(num<max){

          setTimeout(incrementNumber,500);

        }else{

          alert("done");

        }

      }

     setTimeout(incrementNumber,500);

    两段代码可以实现相同的目的。但是可以看出,在使用超时调用时,没有必要跟踪超时调用ID,因为每次执行代码之后,如果不再设置另一次超时调用,调用就会自行停止。一般认为使用超时调用来模拟间歇调用是一种最佳模式。在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动(代码执行事件超长)。而使用超时调用则完全避免。

    系统对话框

    浏览器通过alert(),confirm(),prompt();方法可以调用系统对话框向用户显示信息。系统对话框与浏览器没有关系,由操作系统和浏览器设置决定,而没有css样式。此外,这几个方法打开的对话框都是同步和模态的,即显示这些对话框的时候代码会停止执行,关掉则恢复执行。

    其中var result =  prompt("what's your name?","areis");会如下弹出

    点击确定则返回文本框值,否则返回null。

  • 相关阅读:
    v-for给img的src动态赋值问题
    关于vue+axios上传文件的踩坑分析
    关于nth-of-type和nth-child的关系
    关于fetch
    关于移动端适配
    golang变量作用域问题-避免使用全局变量
    grpc-gateway:grpc转换为http协议对外提供服务
    google的grpc在golang中的使用
    golang中的rpc包用法
    homebrew常用命令
  • 原文地址:https://www.cnblogs.com/shanhm1991/p/8094831.html
Copyright © 2011-2022 走看看