@叨叨老飞

web APIs学习 | 原生JS基础到进阶

日期图标编写于2025年05月13日   修订于2025年06月06日

正文


BOM、DOM

web APIs包含BOM和DOM。

BOM(浏览器对象模型):是浏览器提供的 API,用于操作浏览器窗口、标签页、历史记录、地址栏等浏览器功能。
核心对象:window(顶级对象),包含document、location、navigator、history等子对象。

DOM(Document Object Model——文档对象模型):用来呈现以及与任意HTML或XML文档交互的API,换句话说就是浏览器提供的一套专门用来操作网页内容的功能。最大对象:document。

DOM树:直观体现标签与标签之间的关系。

window (顶级对象)
├── document      // DOM的入口
├── location      // 操作URL
├── navigator     // 浏览器信息
├── history       // 历史记录
├── screen        // 屏幕信息
├── setTimeout()  // 定时器
└── alert()       // 弹窗

获取DOM

document.querySelector('div');  // 选择匹配的第一个元素
document.querySelector('.box'); 
document.querySelector('#box');
document.querySelector('ul li:first-child').style.color = 'red';  // 设置样式

document.querySelectorAll('ul li');  // 获取全部元素,返回伪数组,没有push、pop等方法
document.querySelectorAll('ul li')[0];

document.getElementById('box');
document.getElementsByTagName('div');  // 返回伪数组
document.getElementsByClassName('box');  // 返回伪数组

操作元素内容

对象.innerText;  // 获取内容
对象.innerText = '<strong>aaa</strong>';  // 修改内容,不解析标签,如这里的strong不会被解析为标签,并且“aaa”也不会加粗。

对象.innerHTML = '<strong>aaa</strong>';  // 修改内容,解析标签,如这里的strong会被解析为标签,并且“aaa”也会加粗。

操作元素属性(样式属性)

对象.属性 =;  // 如果存在就更新,如果不存在就新增。

// 通过style形式操作CSS
对象.style.样式属性 =;  // 中划线样式属性改成小驼峰形式书写

// 通过类名的形式操作CSS
对象.className = '';  // 1、由于class是关键字,所以使用className代替;2、className是用新值替换旧值,如果需要添加一个类,需要保留之前的类名。

// 通过classList操作类控制CSS
对象.classList.add('类名');  // 追加
对象.classList.remove('类名');  // 删除
对象.classList.toggle('类名');  // 切换,存在就删除,不存在就添加,类似开关

操作元素属性(表单元素)

// 获取:DOM对象.属性名,表单只能通过value属性获取
对象.value;

// 设置:DOM对象.属性名 = 值
对象.value = 'aaa';

// 单选框、复选框的值为布尔值
对象.checked = true;
// 字符串中的空字符串为false,其余情况为true
对象.checked = 'false';  // 'false'隐式转换布尔值为true

// button的disabled属性(禁用按钮点击)也通过布尔值来设置

H5自定义属性

html5推出的自定义属性,标签一律以data-开头,如“data-id”,dom对象上一律以dataset对象方式获取。

<div data-id='1' data-spm='2'></div>

const one = document.querySelector('div');

// setAttribute方式现在不推荐使用,因为这种方式设置的属性比较乱,随便设置,不便于管理,要让自定义属性定义更标准
// 获取自定义属性
one.dataset.id;
one.dataset.spm;

// 设置自定义属性
one.dataset.id = '2';

定时器-间歇函数

setInterval(函数, 间隔时间);  // 每隔一个间隔时间,调用一次指定函数;

// 定时器返回值为定时器id,数字类型
let n = setInterval(function() {
    ...
}, 1000);

// 关闭定时器
clearInterval(n);  // 参数为定时器id

事件监听

// 事件绑定有两种写法
元素对象.on事件 = function() {}  // 如:onclick
元素对象.addEventListener('事件类型', 函数);
// on的方式会被覆盖,推荐使用addEventListener的方式,可以绑定多次。

// click就是点击事件
let btns = document.querySelectorAll('button');
for (let i = 0; i < btns.length; i ++) {
    btns[i].addEventListener('click', function () {
        document.querySelector('.pink').className = '';
        this.className = 'pink';
    })
}

事件类型

// 鼠标事件
click  // 鼠标点击
mouseenter  // 鼠标经过
mouseleave  // 鼠标离开

// 焦点事件
focus  // 获得焦点
blur  // 失去焦点

// 键盘事件
keydown  // 键盘按键按下触发
keyup  // 键盘按键抬起触发

// 文本事件
input  // 用户输入事件

事件对象

事件对象是有事件触发时的相关信息。例如:鼠标点击事件中,事件对象存储了鼠标点在哪个位置等信息。

使用场景:比如在键盘事件中,可以获取究竟是按下了哪个键,从而做出不同的反应。

如何使用:事件绑定回调函数的第一个参数,通常命名为event、e等。

获取对象属性可以先打印对象,再获取对应的属性。

环境对象

环境对象指函数内部特殊的变量this,它代表着当前函数运行时所处的环境。

this指向的粗略规则:谁调用函数,this就是谁。非严格模式下,普通函数this指向window,事件监听中,指向调用者,箭头函数没有this,this指向可以改变。

回调函数

如果将函数A作为参数传递给函数B时,称A为回调函数。

事件流

事件流是事件完整执行过程中的流动路径,分捕获和冒泡两个阶段。

事件捕获阶段:document → element html → element body → element div(父到子),点击了一下div,捕获的流向

事件冒泡阶段:element div → element body → element html → document(子到父),当一个元素的时间被触发时,同样的事件(如:click)会依次在该元素的所有祖先元素中依次触发。

注:
1、mouseover和mouseout事件有冒泡,mouseenter和mouseleave没有冒泡(推荐)。
2、传统on事件只有冒泡,没有捕获。
<body>
    <div class="father">
        <div class="son"></div>
    </div>

    <script>
        // 第三个参数为布尔值,true表示捕获阶段触发,false表示冒泡阶段触发(默认)
        document.addEventListener('click', function() { console.log('我是爷爷') }, true);
        document.querySelector('.father').addEventListener('click', function() { console.log('我是爸爸') }, true);
        document.querySelector('.son').addEventListener('click', function() { console.log('我是儿子') }, true);
    </script>
</body>

阻止冒泡

默认有冒泡模式的存在,所以很容易影响到父级元素,可以通过阻止冒泡的方式将事件限制在当前元素内。

事件对象.stopPropagation();

解绑事件

传统的on事件可以直接赋值null即可,如:对象.onclick = null;

addEventListener的方式使用:removeEventListener(事件类型, 事件处理函数, [捕获或冒泡阶段]); 

注意:addEventListener方式使用匿名函数无法被解绑。

事件委托

如果同时给多个元素注册事件,一般可以采用for循环来做,事件委托可以只注册一次事件就达到这个效果,原理就是采用了事件冒泡的特点。

document.querySelector('ul').addEventListener('click', function(e) {
    // this是ul,可以通过事件对象的target属性来获取具体点击了哪个对象
    console.dir(e.target);  // e.target就是点击的对象,console.dir用来打印对象
    // 如果要限定点击的元素类别,可以通过对象的tagName属性来判断点击了什么元素
    console.log(e.target.tagName);
})

阻止元素默认行为

e.preventDefault();

其他事件

// 页面加载事件——可以等所有资源加载完成以后再执行js代码,也可以将script代码写到head标签里边
// 事件名:load,监听页面所有资源加载完毕
window.addEventListener('load', function() { ... });  // 给window注册事件
// 事件名:DOMContentLoaded,初始的html文档被完全解析完成以后,该事件触发,无需等待样式表、图像等完全加载,会load快
document.addEventListener('DOMContentLoaded', function() { ... });  // 给document注册事件

// 页面滚动事件
// 事件名:scroll
window.addEventListener('scroll', function() { ... });  // 监听整个页面的滚动
// scrollTop属性:竖向滚动条滚去多少
document.documentElement.scrollTop;  // 整个页面滚了多少
document.documentElement.scrollTop = 100;  // 设置整个页面滚动的初始值 
// document.documentElement 和 document.querySelector('html') 是一样的对象,但是前者是document的属性,可以直接使用,性能开销极小。
// scrollLeft属性:横向滚动条滚去多少

// 页面尺寸事件
// 事件名:resize,窗口尺寸改变时触发事件,可以用来做响应式。
// clientWidth属性、clientHeight属性:可以用来获取元素可见部分的宽和高(不包含边框、margin、滚动条等,包含padding)

元素尺寸与位置

// 获取宽高
// offsetWidth属性 和 offsetHeight属性,和clientWidth、clientHeight的区别是获取的值包含边框,隐藏元素获取到的值为0。

// 获取位置
// offsetLeft属性 和 offsetTop属性,距离自己有定位的父级元素的左、上距离(如某些父元素设置了position,算距离最近的),只读属性。

日期对象

// 日期对象
const date = new Date();
const date = new Date('2025-06-02');

// 日期对象方法
date.getFullYear()
date.getMonth()
date.getDate()
date.getDay()
date.getHours()
date.getMinutes()
date.getSeconds()

时间戳

时间戳可以用来计算倒计时。

// 获取时间戳有三种方法
const date = new Date();
date.getTime();

+new Date();

Date.now();

// 获取指定时间的时间戳,加一个时间参数即可,如下:
+new Date('2025-06-02 08:00:00');

节点操作

// 查找节点
// 父节点
子元素.parentNode
// 子节点
父元素.childNodes  // 得到全部信息,不推荐使用
父元素.children  // 返回伪数组
// 兄弟节点
document.querySelector('ul li:nth-child(2)');
元素.nextElementSibling  // 下一个兄弟节点
元素.previousElementSibling  // 上一个兄弟节点

// 增加节点
// 1、创建节点
const e = document.createElement('标签名');
e.innerHTML= `...`;
// 2、追加节点
父元素.appentChild(要插入的元素);  // 插入到父元素的最后一个元素
父元素.insertBefore(要插入的元素, 在哪个元素前边);  // 插入到指定元素前边,第二个参数可以这样写:ul.children[0]

// 克隆节点
元素.cloneNode(布尔值);  // 默认false,true表示会包含后代节点一起克隆,false表示克隆时不包含后代节点。

// 删除节点
父元素.removeChild(要删除的元素);

移动端时间

touchstart事件:手指触摸到一个DOM元素时触发

touchmove事件:手指在一个DOM元素上滑动时触发

touchend事件:手指从一个DOM元素上移开时触发

JS插件

swiper轮播图插件

BOM(浏览器对象模型)

BOM是浏览器对象模型,BOM是整个浏览器,BOM包含DOM,还包含navigator、location、history、screen等。

window是最大的对象,window对象的属性和方法在调用时可以省略window,如直接用document调用方法,而不是window.document。

定时器——延时函数

// 延时执行回调函数,只执行一次
let timer = setTimeout(回调函数, 等待毫秒数)

// 清除延时函数
clearTimeout(timer);

JS执行机制

js代码是从上往下顺序执行。浏览器有两种引擎,一种是渲染引擎,一种是js解析器,如谷歌浏览器是v8引擎。

js是单线程语言,这就意味着所有任务都需要排队,前一个任务结束,才会执行下一个任务,如果遇到耗时的任务,就会造成页面阻塞,为了解决这个问题,利用多核CPU的计算能力,H5提出Web Worker标准,运行js脚本创建多个线程,js中出现了同步、异步。

同步和异步的区别就是流水线上各个流程的执行顺序不同。

同步任务在主线程上执行,形成执行栈。

异步任务有三种类型:

1、普通事件,如:click、resize等;
2、资源加载,如:load、error等;
3、定时器,包括setInterval、setTimeout等;

异步任务添加到任务队列中。

js先执行执行栈中的同步任务,异步任务放在任务队列中,一旦执行栈中的所有同步任务执行完毕,系统会依次读取任务队列中的异步任务,被读取的异步任务进入执行栈开始执行。

事件循环:主线程不断的重复获得任务、执行任务、再获得任务、再执行,这种机制被称为事件循环。

location对象

location对象拆分并存储了url地址的各个组成部分。

常用属性和方法:

href:获取完整的url地址,赋值时可以地址跳转。

search:url地址中?及后边的部分。

hash:哈希,url地址中#及之后的部分,单页面应用,如网易云音乐中:https://www.music.163.com/#/download。

reload():刷新,传入参数true是强制刷新。

navigator对象

获取浏览器相关信息。

userAgent属性常用。

history对象

管理历史记录,该对象与浏览器地址栏操作相对应,如前进、后退、历史记录等。

常用属性和方法:

back():后退。

forward():前进。

go(参数):前进后退功能,参数是1就前进一个页面,参数是-1就后退一个页面。

本地存储-localStorage

H5新增了本地存储功能,以键值对的形式存储在浏览器中,只能存储字符串类型,不能跨域读取,关闭浏览器不会消失,除非手动删除,否则数据永久存储在用户电脑。

// 存储数据
localStorage.setItem(key, value);

// 读取数据
localStorage.getItem(key);

// 删除数据
localStorage.removeItem(key);

// 存取复杂数据类型的数据(本地存储只能存储字符串类型的数据)
const obj = {
    name: 'aaa',
    age: 18,
    gender: '男'
}
// 存储
localStorage.setItem('obj', JSON.stringify(obj));  // 将对象类型转换为json字符串
// 读取
JSON.parse(localStorage.getItem('obj'));  // json字符串转回对象

在浏览器中查看详情

图片

本地存储-sessionStorage

关闭浏览器窗口数据消失,同一个窗口(页面)下数据可以共享,也是键值对存储,使用同localStorage。

map() 和 join() 数组方法实现字符串拼接

// map可以遍历数组处理数据,并且返回新的数组
const arr = ['a', 'b', 'c']
const newArr = arr.map(function(item, index) {
    return item + '-1';
});  // ['a-1', 'b-1', 'c-1']

// join可以吧数组中的元素转换成一个字符串
newArr.join(',');  // a-1,b-1,c-1,不传参数默认是英文逗号

正则表达式

const str = 'aaabbbcccddd';
// 定义规则
const reg = /ab/;
// 检测方法
reg.test(str);  // 用来查看正则表达式与指定字符串是否匹配,返回true、false
reg.exec(str);  // 在一个字符串中执行一个搜索匹配,如果匹配成功,返回数组,否则返回null

参考


学习视频是b站《黑马程序员前端JavaScript入门到精通全套视频教程》。

更多信息可参考权威网站

相关文章


前一篇:基础语法扫盲 | 原生JS基础到进阶