Web - Javascript 函数与DOM、BOM

152 阅读12分钟

概述

深入浅出讲解JS函数、作用域与DOM操作,涵盖事件处理、定时器及BOM核心知识,搭配实用代码示例,助你高效掌握前端开发必备技能!

函数

  • 函数就是语句的封装,可以让这些代码方便地被复用
  • 函数具有“一次定义,多次调用”的优点

定义

  • 和变量类似,函数必须先定义然后才能使用
  • 使用function关键字定义函数,function是“功能”的意思

函数的提升

  • 和变量声明提升类似,函数声明也可以被提升,就是说JavaScript在执行脚本时首先会预加载执行脚本中的内容,函数可以调用在前,声明在后。
fun();
function fun(){
    alert("函数被执行");
}
  • 如果函数是用函数表达式的写法定义的,则没有提升特性
fun();
var fun = function (){
    alert("函数被执行");
}

参数

  • 参数是函数内的一些待定值,在调用函数时,必须传入这些参数的具体值

  • 函数可以没有参数,也可以有多个参函数的参数可多可少,数,多个参数之间需要用逗号隔开

  • 函数内arguments表示它接收到的实参列表,它是一个类数组对象

  • 类数组对象:所有属性均为从0开始的自然数序列,并且有length属性,和数组类似可以用方括号书写下标访问对象的某个属性值,但是不能调用数组的方法

function add(){
  console.log(arguments);
}
add(3,5);

递归和克隆

函数的内部语句可以调用这个函数自身,从而发起对函数的一次迭代。在新的迭代中,又会执行调用函数自身的语句,从而又产生一次迭代。当函数执行到某一次时,不再进行新的迭代,函数被一层-层返回,函数被递归。

递归是一种较为高级的编程技巧,它把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。

2、递归的要素

  • 边界条件:确定递归到何时终止,也称为递归出口
  • 递归模式:大问题是如何分解为小问题的,也称为递归体

变量

1、变量的作用域

局部变量:JavaScript是函数级作用域编程语言:变量只在其定义时所在的function内部有意义,形参也是局部变量。

全局变量:如果不将变量定义在任何函数的内部,此时这个变量就是全局变量,它在任何函数内都可以被访问和更改。

2、遮蔽效应

如果函数中也定义了和全局同名的变量,则函数内的变量会将全局的变量遮蔽。

3、作用域链

先来认识函数的嵌套:一个函数内部也可以定义一个函数和局部变量类似,定义在一个函数内部的函数是局部函数。

在初次给变量赋值时,如果没有加var关键字,则将定义全局变量

4、闭包

JavaScript中函数会产生闭包(closure), 闭包是函数本身和该函数声明时所处的环境状态的组合。

闭包用途:当闭包产生时,函数所处环境的状态会始终保持在内存中,不会在外层函数调用后被自动清除,这就是闭包的记忆性。

DOM

DOM( Document Object Model,文档对象模型)是 JavaScript 操作HTML文档的接口,使文档操作变得非常优雅、简便。

DOM最大的特点就是将文档表示为节点树。

1、节点操作

  • 改变元素节点中的内容可以使用两个相关属性
  • innerHTML属性能以HTML语法设置节点中的内容
  • innerText属性只能以纯文本的形式设置节点中的内容

2、创建节点

  • document.createElement()方法用于创建一个指定tag name的HTML元素
  • 新创建出的节点是“孤儿节点”这意味着它并没有被挂载到DOM树上,我们无法看见它
  • 必须继续使用appendChild()insertBefore()方法将孤儿节点插入到DOM树上
  • 任何已经在DOM树上的节点,都可以调用appendChild()方法,它可以将孤儿节点挂载到它的内部,成为它的最后一个子节点
  • 任何已经在DOM树上的节点,都可以调用insertBefore()方法,它可以将孤儿节点挂载到它的内部,成为它的“标杆子节点”之前的节点。
var oBox = document.getElementById('box');
var oP = document.createElement('p');

oP.innerText = '我是新来的';
oBox.appendChild(oP);
  • 如果将已经挂载到DOM树上的节点成为appendChild()或者insertBefore()的参数,这个节点将会被移动。
  • 这意味着一个节点不能同时位于DOM树的两个位置。

3、删除节点

  • removeChild()方法从DOM中删除一个子节点,节点不能主动删除自己,必须由父节点删除它

4、克隆节点

  • cloneNode()方法可以克隆节点,克隆出的节点是孤儿节点。
  • cloneNode()参数是一个布尔值,表示是否采用深度克隆:如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克隆该节点本身

5、修改节点的css样式

  • 改变元素节点的CSS样式需要使用这样的语句,CSS属性要写成“驼峰”形式。
  • 标准W3C属性,如src、hre等等,只需要直接打点进行更改即可,不符合W3C标准的属性,要使用setAttribute()getAttribute()来设置、读取。

6、访问元素节点

  • 所谓“访问”元素节点,就是指“得到“获取”页面上的元素节点。
  • 对节点进行操作,第一步就是要得到它,访问元素节点主要依靠document对象。
  • document对象是DOM中最重要的东西,几乎所有DOM的功能都封装在了document对象中。
  • document对象也表示整个HTML文档,它是DOM节点树的根。
  • document对象的nodeType属性值是9。
  • document.getElementByld()功能是通过id得到元素节点,如果页面上有相同id的元素,则只能得到第一个,不管元素藏的位置有多深,都能通过id把它找到。
  • getElementsByTagName()方法的功能是通过标签名得到节点数组,数组方便遍历,从而可以批量操控元素节点,即使页面上只有一个指定标签名的节点,也将得到长度为1的数组。
  • 任何一个节点元素也可以调用getElementsByTagName()方法,从而得到其内部的某种类的元素节点。
  • getElementsByClassName()方法的功能是通过类名得到节点数组,getElementsByClassName()方法从IE9开始兼容,某个节点元素也可以调用getElementsByClassName()方法从而得到其内部的某类名的元素节点。
  • querySelector()方法的功能是通过选择器得到元素,querySelector()方法只能得到页面上一个元素,如果有多个元素符合条件,则只能得到第一个元素。
  • querySelectorAll()方法的功能是通过选择器得到元素数组,即使页面上只有一个符合选择器的节点,也将得到长度为1的数组。

7、延迟运行

  • 在测试DOM代码时,通常JS代码一定要写到HTML节点的后面,否则JS无法找到相应HTML节点
  • 可以使用window.onload =function(){}事件,使页面加载完毕后,再执行指定的代码

DOM 事件

事件监听:DOM允许我们书写JavaScript代码以让HTML元素对事件作出反应,就是让计算机随时能够发现这个事件发生了,从而执行程序员预先编写的一些程序。

设置事件监听的方法主要有onxxxaddEventListener()两种,二者的区别将在事件传播一课中介绍。

1、常见的鼠标事件监听

事件名事件描述
onclick当鼠标单击某个对象
ondblclick当鼠标双击某个对象
onmousedown当某个鼠标按键在某个对象上被按下
onmouseup当某个鼠标按键在某个对象上被松开
onmousemove当某个鼠标按键在某个对象上被移动
onmouseenter当鼠标进入某个对象(相似事件onmouseover)
onmouseleave当鼠标离开某个对象(相似事件onmouseout)

2、常见的键盘事件监听

事件名事件描述
onkeypress当某个键盘的键被按下(系统按钮如箭头键和功能键无法得到识别)
onkeydown当某个键盘的键被按下(系统按钮可以识别并且会先于onkeypress发生)
onkeyup当某个键盘的键被松开

3、常见的表单事件监听

事件名事件描述
onchange当用户改变域的内容
onfocus当某元素获得焦点(比如tab键或鼠标点击)
onblur当某元素失去焦点
onsubmit当表单被提交
onreset当表单被重置

4、常见的页面事件监听

事件名事件描述
onload当页面或图像被完成加载
onunload当用户退出页面

事件传播

当盒子嵌套时事件监听的执行顺序,事件的传播是:先从外到内,然后再从内到外。

事件对象

var oBox = document.getElementById('box');
oBox.onmousemove = function (e){
    //对象e就是这次事件的事件对象
};

鼠标位置:鼠标位置计算的是最内存的元素。

属性属性描述
clientX鼠标指针相对于浏览器的水平坐标
clientY鼠标指针相对于浏览器的垂直坐标
pageX鼠标指针相对于整张网页的水平坐标
pageY鼠标指针相对于整张网页的垂直坐标
offsetX鼠标指针相对于事件源元素的水平坐标
offsetY鼠标指针相对于事件源元素的垂直坐标

对象属性e.charCode、e.keyCode、e.preventDefault()、e.stopPropagation()

  • e.charCode属性通常用于onkeypress事件中,表示用户输入的字符的字符码。
  • e.keyCode属性通常用于onkeydown事件和onkeyup中,表示用户按下的按键的"键码"。
  • e.preventDefault()方法用来阻止事件产生的"默认动作"一些特殊的业务需求,需要阻止事件的“默认动作”。
  • e.stopPropagation()方法用来阻止事件继续传播在一些场合,非常有必要切断事件继续传播,否则会造成页面特效显示出bug。

事件委托

每一个事件监听注册都会消耗一定的系统内存,而批量添加事件会导致监听数量太多,内存消耗会非常大。

实际上,每个<li>的事件处理函数都是不同的函数,这些函数本身也会占用内存,利用事件冒泡机制,将后代元素事件委托给祖先元素。

动态绑定事件的问题:

  • 新增元素必须分别添加事件监听,不能自动获得事件监听
  • 大量事件监听、大量事件处理函数都会产生大量消耗内存

事件委托:事件委托通常需要结合使用e.target属性。

属性属性描述
target触发此事件的最早元素,即"事件源元素"
currentTarget事件处理程序附加到的元素

使用场景:

  • 当有大量类似元素需要批量添加事件监听时,使用事件委托可以减少内存开销。
  • 当有动态元素节点上树时,使用事件委托可以让新上树的元素具有事件监听。

1、onmouseenter和onmouseover都表示“鼠标进入”,它们有什么区别呢?

:onmouseenter不冒泡,onmouseover冒泡

定时器

1、创建定时器

setInterva1()函数可以重复调用一个函数,在每次调用之间具有固定的时间间隔。

setInterval(function (){
    console.log('setInterval');
},2000);

setInterva1()函数可以接收第3、4.个参数,它们将按顺序传入函数,具名函数也可以传入setInterval。

setInterval(function (a,b){
    console.log('setInterval');
},2000,86,66);


var a = 0;
function fun(){
    console.log(++a);
}
setInterval(fun,2000);

2、清除定时器

 //设置定时器,并且用timer变量接收这个定时器
 var timer = setInterval(function () {

 },2000);

 //点击按钮时,清除定时器
 oBtn.onclick = function () {
     clearInterval(timer);
 }

3、延时器

setTimeout()函数可以设置一个延时器,当指定时间到了之后,会执行函数一次,不再重复执行。

clearTimeout()函数可以清除延时器,和clearInterval() 非常类似。

BOM 基础

BOM(Browser Object Model,浏览器对象模型)是Js与浏览器窗口交互的接口。

1、window对象

  • window对象是当前JS脚本运行所处的窗口,而这个窗口中包含DOM结构,window.document属性就是document对象。
  • 在有标签页功能的浏览器中,每个标签都拥有自己的window对象;也就是说,同一个窗口的标签页之间不会共享一个 window 对象。
  • setlnterval()、alert()等内置函数,普遍是window的方法。

窗口尺寸相关属性

属性意义
innerHeight浏览器窗口的内容区域的高度,包含水平滚动条(如果有的话)
innerwidth浏览器窗口的内容区域的宽度,包含垂直滚动条(如果有的话)素
outerHeight浏览器窗口的外部高度
outerwidth浏览器窗口的外部宽度
  • 在窗口大小改变之后,就会触发resize事件,可以使用window.onresize或者window.addEventListener('resize')来绑定事件处理函数。
  • window.scrolIY属性表示在垂直方向已滚动的像素值。
  • document.documentElement.scrollTop属性也表示窗口卷动高度。
  • 在窗口被卷动之后,就会触发scroll事件,可以使用window.onscroll或者window.addEventListener('scroll')来绑定事件处理函数

2、navigator对象

  • window.navigator 属性可以检索navigator对象,它内部含有用户此次活动的浏览器的相关属性和标识。
属性意义
appName浏览器官方名称
appVersion浏览器版本
userAgent浏览器的用户代理(含有内核信息和封装壳信息)
platform用户操作系统

3、history对象

window.history 对象提供了操作浏览器会话历史的接口,常用操作就是模拟浏览器回退按钮。

history.back();
history.go(-1);

4、location对象

  • window.location标识当前所在网址,可以通过给这个属性赋值命令浏览器进行页面跳转。
  • 可以调用locationreload方法以重新加载当前页面参数true表示强制从服务器强制加载。
  • window.location.search属性即为当前浏览器的GET请求查询参数。