EMCAScript的定义,更多的是在编程语言的方面进行定义,如果在Web中使用JavaScript,则BOM模型才是JavaScript语言的核心.BOM模型提供了很多对象,用于访问浏览器的很多功能,这些功能与网页的内容是无关的.BOM学习博客地址

BOM模型

BOM(Browser Object Model)模型是浏览器对象模型.

window对象

window对象表示浏览器的一个窗口的实例.也是ECMAScript规定的全局对象.网页中定义的任何一个全局变量,对象,函数,都是window对象的属性.

属性或者方法 说明
window.innerHeight 浏览器窗口的内部高度
window.innerWidth 浏览器窗口的内部宽度
window.open() 打开新窗口,open可以加第一个参数表示URL,第二个参数表示窗口名,第三个参数用于一些控制
window.close() 关闭当前窗口

navigator对象

浏览器对象,通过这个对象可以判定用户所使用的浏览器,包含了浏览器相关信息。是window的子对象.通过navigator取得的信息并不精准,因为浏览器设置可以伪造这些信息.

属性或者方法 说明
navigator.appName Web浏览器全称
navigator.appVersion Web浏览器厂商和版本的详细字符串
navigator.userAgent 客户端信息
navigator.platform 浏览器所在的操作系统

screen对象

表示屏幕对象,不常用.
screen.availWidth – 可用的屏幕宽度
screen.availHeight – 可用的屏幕高度

history对象

window.history 对象包含浏览器的历史。浏览历史对象,包含了用户对当前页面的浏览历史,但我们无法查看具体的地址,可以简单的用来前进或后退一个页面。
history.forward() // 前进一页
history.back() // 后退一页

location对象

window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。
location.href 获取URL
location.href=”URL” // 跳转到指定页面
location.reload() 重新加载页面

弹出框

浏览器通过alert(), confirm(), prompt()三个方法调用系统对话框向用户显示消息.这些对话框与网页没有关系,也不包含HTML和CSS,在显示对话框的时候,HTML页面内的代码是停止执行的,说明对话框程序是同步的.

属性或者方法 说明
alert() 内部参数是字符串,会在提示框中显示出来,一般用在向用户通知他们无法控制的消息
confirm() 参数也是字符串,这个框除了OK按钮之外 ,还有一个Cancel按钮,用户点击了哪个,就会通过confirm()返回对应的布尔值
prompt() 除了OK和Cancel之外,还有一个文本输入区域,用于提示用户输入一些内容.Prompt接受两个参数,一个是显示的提示信息,一个是文本输入区域的默认值.如果用户单击了OK,会返回文本区域的值,如果用户单击了Cancel,会返回Null.

定时器

定时器有两个函数,用法类似:

var timer = setTimeout(function(){alert(123);}, 3000)
clearTimeout(timer);

第一个语句的setTimeout函数接受两个参数,第一个是JS语句或者是一个函数,第二个数值是以毫秒,一旦设置了timer,第一个参数中的JS代码就会在第二个参数指定后的时间后运行.将其赋给一个变量的话,就可以用clearTimeout(变量名)来取消该定时器.setTimeout是一次性的定时器,除此之外还有一个间隔一定时间反复执行的定时器:

// 每隔一段时间就执行一次相应函数
var timer = setInterval(function(){console.log(123);}, 3000)
// 取消setInterval设置
clearInterval(timer);

定时器也是由浏览器提供的功能,定时器本身的间隔受到浏览器的精确程度影响,比如ie的间隔最小为4ms.因此定时器不应该设置的过短.


DOM模型-选择和操作节点元素

DOM模型应该说是大家为什么要使用JavaScript的原因,也就是可以方便的操作HTML页面内的所有元素,以及做到HTML和CSS做不到的事情,就是动态的修改网页内容以及提供事件响应.
当网页被加载的时候,浏览器会创建页面的文档对象模型,是一个树结构.只要将一个JS文件引入HTML页面,则这个JS文件里的代码就可以操作这个页面的DOM模型.在DOM里提到元素和节点,基本是一个意思,都是指的被选中的HTML标签及其全部内容
DOM标准规定HTML文档中的每个成分都是一个节点(node):

  • 文档节点(document对象):代表整个文档
  • 元素节点(element 对象):代表一个元素(标签)
  • 文本节点(text对象):代表元素(标签)中的文本
  • 属性节点(attribute对象):代表一个属性,元素(标签)才有属性
  • 注释是注释节点(comment对象)

JavaScript 通过DOM模型,可以改变页面内所有的HTML元素,内容,样式和响应事件,这样就可以创建动态网页.DOM是JavaScript作为前端开发语言最重要的内容.

查找节点

查找节点即定位节点,有若干种办法. 将查找的结果赋值给变量,该变量即存储了找到的节点.定位节点之后就可以针对该节点进行增删改操作.

直接查找
document.getElementById 根据ID获取一个标签,由于ID是唯一的,直接返回的就是节点对象
document.getElementsByClassName 根据class属性获取,由于一般类是多个,所以返回的是一个包含节点对象的数组
document.getElementsByTagName 用标签名称选元素,返回的也是数组
间接查找
parentElement 父节点标签元素,直接返回一个节点元素
children 所有子节点元素,返回的是一个数组
firstElementChild 第一个子元素,返回节点对象,如果不存在,返回undefined
lastElementChild 最后一个子元素,返回节点对象,如果不存在,返回undefined
nextElementSibling 返回下一个兄弟元素
previousElementSibling 返回上一个兄弟元素

操作节点

创建节点
document.createElement(“tagname”); 创建一个标签元素,其中的tagname是符合HTML标准的标签名,创建节点常用原生的JS语句
添加节点
node.appendChild(newnode) 这个是将newnode节点添加到node节点的子元素中,作为node节点的最后一个子元素.在定义了一个元素后,反复插入这个元素,会发现这个元素只能同时出现在一处,想要插入新元素,就必须再创建一个元素.
fathernode.insertBefore(newnode,node); 首先需要定位node的父标签,然后将newnode插入到node标签之前,做为node标签的上一个兄弟元素.
删除节点
node.removeChild(targetnode) 需要获得要删除的元素的父元素,然后采用该方法删除元素
替换节点
fathernode.replaceChild(newnode, targetnode); 也需要定位需替换节点的父元素,然后替换该节点
修改节点属性和内容
divEle.innerText 取得文本部分的值,可以对其进行设置,设置的时候全部是字符串,即使有标签字样也会解释成字符串.注意,如果对父元素使用,取值会取自己加所有子元素的文本内容 , 如果修改会影响所有的东西,包括嵌套的标签.
divEle.innerHTML 获取这个节点开始和结束标签之间的HTML内容.如果设置的话,值中如果有符合HTML标签的字样,会被解释成标签.
node.内置属性名 = ‘值’ 对于内置属性名,可以直接通过属性名赋值,比如src,href等属性
node.setAttribute(“age”,”18″) Attribute用来操作自定义属性,这个是设置自定义属性与值
node.getAttribute(“age”) 获取自定义属性
node.removeAttribute(“age”) 删除自定义属性

获取值

获取值通过value属性,只能作用于input,select,textarea这三个表单元素.
value对于text获取的是输入的值或者被选中的选项标签里设置的value属性,对于select是菜单选项标签的value,对于textarea是输入的值,经常用在表单提交的事件中,对表单元素的值进行验证.

操作节点的class属性

在选择到具体的节点之后,可以通过classList属性来操作这个标签的类属性.

操作class属性
node.className 获取class属性的内容,是一个字符串,只能看,不能操作
node.classList 返回一个类的列表,用空格区分开的类名是列表的一个元素,相比获得字符串,获得类列表可以用来操作类属性
classList.add(cls) 给节点增加一个类
classList.contains(cls) 判断这个元素是否属于某个类,也就是列表中是否包含类名,是则返回true,不是则返回false
classList.toggle(cls) 切换类,每次执行,如果类列表内有类名,就会删除该类,如果没有类名,就会添加类.通常用来实现一些在两种样式之前切换的效果.

操作节点的CSS属性

操作CSS属性
node.style 获取一个节点的所有css属性的集合,如果在浏览器里可以看到,是一个很长的列表,一般不单独使用
node.style.CSS属性名=’值’ 操作CSS属性,注意css属性中用短横线连接,在JS里改成了驼峰命名

DOM模型-事件

目前通过JS已经可以操作一个页面所有的HTML标签的内置属性以及CSS样式了,即可以操作静态页面的所有内容.为了让页面实现动态交互,很重要的就是对事件的捕捉和处理.
JS处理事件的逻辑是–所有的标签都有一些事件–选择需要侦听哪些事件–当事件发生的时候,用JS函数来处理–处理的结果呈现在页面上.

常用事件
onclick 当用户点击某个对象时调用的事件句柄
ondblclick 当用户双击某个对象时调用的事件句柄
onfocus 当元素获得焦点,通常使用在输入框上
onblur 元素失去焦点,常用在用户输入完之后移动到其他地方,这个时候可以对输入内容进行验证
onchange 域的内容被改变,常用在select元素里边的内容改变的时候
onsubmit 表单中的submit按钮被按下的时候,常用在表单与后端交互的时候
onkeydown 某个键被按下
onkeypress 某个键按下以后松开的时候
onkeyup 某个键被松开,这些侦听按键的事件,通常用在写一些web游戏中
onmousedown 鼠标按键被按下
onmousemove 鼠标移动
onmouseout 鼠标从某元素上移动开
onmouseover 鼠标移动到某元素之上,这一系列鼠标的效果经常用在弹出菜单等特效上
onselect 在文本框中的文本被选中时发生
onselect 在文本框中的文本被选中时发生

操作事件的例子

<!--点击某个元素会变色-->
<div id="change" onclick="changeColor(this)">div</div>
<script>
  function changeColor(ths) {
    ths.style.backgroundColor="green";
  }
</script>

在JS语句内,定义的是函数,ths是形参,表示调用这个函数的对象,调用的时候,这个函数绑定的对象就是这个标签.ths形参指的是这个标签对象.

在实际使用该函数的时候,在标签内部的需要把事件名称和函数关联起来,且给函数传递实参. 这里的实参this是一个关键字,就表示当前的对象自己(类似于python里的self).

这段代码的意思就是div标签的onclick事件发生的时候,调用changeColor函数,将自己传入给这个函数,修改自己的CSS背景颜色属性为绿色.

定时器实例

// 让一个文本框里显示时间.两个按钮,一个启动显示时间,一个停止并且清除文本框.
// 先建立三个元素
<input type="text" id="in">
<input type="button" id="start" onclick="refreshTimer()" value="开始">
<input type="button" id="stop" onclick="stopTimer()" value="停止">

<script>
// 因为不同的函数都要操作定时器,所以将定时器设置为全局变量
    var input = document.getElementById('in');
    var t = null;
// 修改input.value的函数
    function startTimer() {
        var current_time = new Date();
        input.value = current_time.toLocaleString();
    }
// 定时器函数,间隔1秒反复执行修改input.value的函数,绑定给开始按钮
    function refreshTimer() {
        t = setInterval(startTimer, 1000)
    }
// 停止定时器且清空input.value的函数,绑定给停止按钮
    function stopTimer() {
        clearInterval(t);
        input.value = '';
    }
</script>

但这个程序其实有BUG,如果双击开始,则会发现停不掉定时器,这是因为点击两次的时候,虽然变量相同,但t等于对应了一个新的定时器,老的定时器依旧在运行,只不过t不再指向老的定时器,所以清除不掉.
这里只需要在生成定时器的时候判断一下t的值,如果t!==undefined,就不再设置新的定时器,然后在定时器结束的代码里,加上t=undefined即可.修改后的程序是这样的:

<body>
// 让一个文本框里显示时间.两个按钮,一个启动显示时间,一个停止并且清除文本框.
// 先建立三个元素
<input type="text" id="in">
<input type="button" id="start" onclick="refreshTimer()" value="开始">
<input type="button" id="stop" onclick="stopTimer()" value="停止">

<script>
    // 因为不同的函数都要操作定时器,所以将定时器设置为全局变量
    var input = document.getElementById('in');
    var t;
    // 修改input.value的函数
    function startTimer() {
        var current_time = new Date();
        input.value = current_time.toLocaleString();
    }
    // 如果T是未定义,才启动定时器,如果T有值,就跳过.
    function refreshTimer() {
        if (t == undefined) {
            t = setInterval(startTimer, 1000)
        }
    }
    // 停止定时器,重新把t赋值undefined,绑定给停止按钮
    function stopTimer() {
        clearInterval(t);
        input.value = '';
        t = undefined;
    }
</script>

这个例子说明一个页面内不要存在同种的多个定时器
改进一下,用一个按钮来控制,先修改标签名称然后进行判断,就不会启动多个定时器.:

<input type="text" id="in">
<input type="button" id="start" onclick="pressed()" value="开始">


<script>


    const input = document.getElementById('in');
    const button = document.getElementById('start');
    var t = null;

    function pressed() {
        if (button.value === "开始") {
            button.value = '停止';
            refreshTimer();
        } else {
            stopTimer();
        }
    }


    function startTimer() {
        var current_time = new Date();
        input.value = current_time.toLocaleString();
    }

    function refreshTimer() {
        t = setInterval(startTimer, 1000)
    }

    function stopTimer() {
        clearInterval(t);
        input.value = '';
        button.value = '开始'
    }
</script>