JavaScript 学习笔记
引入
JavaScript 是一种轻量级、跨平台和解释编译的编程语言,也称为网页脚本语言。它以开发网页而闻名,但是许多非浏览器环境也可以使用它。JavaScript 可用于客户端开发以及服务器端开发。它既是命令式又是声明式语言。作为前端三件套之中唯一有编程逻辑的语言,JavaScript 常常用于页面交互、实现一些复杂的动画以及数据传输等。
浏览器工作原理
浏览器分为两个部分:渲染引擎和 JS 引擎
- 渲染引擎:用来解析HTML和CSS,俗称内核,比如 chrome 的blink,老版本的 webkit
- JS 引擎:也成为 JS 解释器。用来读取网页中的 JavaScript 代码,对其进行后台处理,比如 chrome 浏览器的 v8
注意:浏览器本身不会执行 JS 代码,而是通过内置 JavaScript 引擎(解释器)来执行JS代码,JS 引擎执行代码时会逐行解释每一行源码(转化为机器语言),然后由计算机去执行
JS 组成
ECMAScript
ECMAScript 是由 ECMA 国际(原欧洲计算机制造商协会)进行标准化的一门编程语言,它规定了 JS 的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套 JS 语法工业标准
DOM
DOM(Document Object Model,文档对象模型)是 W3C 组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口。通过此接口我们可以很容易的对页面上的元素的属性进行操作
BOM
BOM(Browser Object Model,浏览器对象模型)是一种独立于内容的,与浏览器窗口进行互动的对象结构。通过 BOM 可以操作浏览器窗口,比如弹出框、浏览器跳转、获取窗口大小、滚动条、分辨率等
JS 数据类型及运算符
JS 是一种弱类型的语言,也就是说某一个变量被定义类型之后,该变量可以根据环境变化自动进行转换,不需要强制转换
字符串
使用单引号或双引号包裹
\ 为转义字符,通过 \ ,可以打印 Unicode Ascll 字符等
多行字符串编写
1 | var msg = ` |
- 模板字符串
1 | let name = 'Pillage' |
- 字符串长度
1 | str.length |
- 可变性:不可变
- 大小写转化(对中文没有影响)
1 | .toUpperCase(); |
- 寻找索引
1 | .indexOf('t') |
- 截取字符串
1 | .substring(1) //从下标为1开始截取,包括下标为1的,一直截到最后 |
数组
注意:for in 是遍历下标, for of 才是遍历数组具体的值
Array 可以包含任意的数据类型
1 | let array = [1, 2, 3, "Hello"] |
- 长度
1 | array.length |
注意:此属性可读可写,即可以通过赋值修改数组的大小
- 寻找索引
1 | array.indexOf(1) |
- 截取数组,返回一个新数组
1 | array.slice() |
类似于 String 中的 substring
- 操作元素(在尾部)
1 | array.push() |
- 操作元素(在头部)
1 | array.unshift //压入到头部 |
- 排序
1 | array.sort() |
- 元素反转
1 | array.reverse() |
- 数组拼接
1 | array.concat([1, 2, 3]) |
注意:concat() 并不会修改原数组,只会返回一个连接后的新数组
- 连接数组
打印拼接数组,使用特定的字符串连接
1 | array.join('') |
- 多维数组
类似于 Python。例如二维数组就是一个普通一维数组中的每一个元素又是一个一维数组
对象
定义:
1 | var 对象名 = { |
JS 中,大括号可以表示一个对象,用键值对描述属性,多个属性之间用逗号隔开,最后一个不需要逗号
JS 中,所有的键都是字符串,值可以是任意类型
- 对象赋值
1 | person.age = 19 |
- 动态增删属性
1 | //动态删减 name 属性 |
- 判断某个属性值是否在这个对象中 xxx in xxx
注意:因为继承机制的存在,所以父类有的属性,子类也会被判定为有 如:
1 | 'toString' in person |
- 判断某个属性是否在这个对象本身中 hasOwnProperty
1 | person.hasOwnProperty('toString') |
注意:Map 和 Set 是 ES6 新特性
Map
定义:
1 | var map = new Map([['tom', 100], ['jerry', 99]]) |
用二维数组的形式可以直接 new 出来
元素操作:
1 | var name = map.get('tom') //通过键获取值 |
Set
无序不重复集合,Set 会自动进行去重操作
定义:
1 | var set = new set([1, 2, 3]) |
操作元素:
1 | set.add(4) //增加元素 |
遍历
forEach 循环
1 | let array = [5, 6, 7] |
iterator 迭代器
遍历数组:
1 | let array = [5, 6, 7] |
遍历 Map 和 Set:
1 | let map = new Map([['Tom', 100], ['Jerry', 99]]) |
变量转换
通过 typeof 变量名 可以输出变量的类型
- String 转数字:
1 | parseInt();//转为整数 |
- 强制类型转换
1 | Boolean(value);//把给定的值转换成Boolean型; |
注意:用这三个函数之一转换值,将创建一个新值,存放由原始值直接转换成的值。这可能会造成意想不到的后果。
逻辑运算符
与 && 或 || 非!
比较运算符:
1 | = //赋值运算符 |
注意:
NaN 与任何数值都不相等,包括自己
1 | NaN === NaN //false |
只能通过 isNaN(NaN) 这个方法来判断一个数是否为 NaN
JS 常用输入输出方法
| 方法名 | 方法的作用 | 参数解释 |
|---|---|---|
| alert(msg) | 浏览器弹出带有信息的警示框 | msg:要显示的信息 |
| console.log(meg) | 浏览器控制台打印信息 | msg:要打印的信息 |
| console.dir(v) | 控制台打印元素对象,从而查看里面的属性和方法 | v:变量名 |
| prompt(msg) | 浏览器弹出带有一段消息的输入框,获取输入 | msg:显示消息,返回值:用户输入内容 |
| confirm(msg) | 浏览器弹出带有一段消息的确认框 | msg:显示消息,返回值:bool类型用户是否确认 |
DOM 基础
基本操作
关于 dom 的基操,主要内容有 创建、增、删、改、查、属性操作、事件操作
- 创建
1 | document.write |
- 增
1 | appendChild |
- 删
1 | removeChild |
- 改
1 | 主要修改 dom 的元素属性,dom 元素的内容、属性,表单的值等 |
- 查
1 | 主要获取查询 dom 的元素 |
- 属性操作
1 | 主要针对于自定义属性 |
- 事件操作
给元素注册事件,采取 事件源.事件类型 = 事件处理程序
| 鼠标事件 | 触发条件 |
|---|---|
| onclick | 鼠标点击左键触发 |
| onmouseover | 鼠标经过触发 |
| onmouseout | 鼠标离开触发 |
| onfocus | 获得鼠标焦点触发 |
| onblur | 失去鼠标焦点触发 |
| onmousemove | 鼠标移动触发 |
| momouseup | 鼠标弹起触发 |
| onmousedown | 鼠标按下触发 |
DOM 获取元素
1 | document.getElementById();//属性名 |
事件
事件三要素:事件源、事件类型、事件处理程序
执行事件的步骤:
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
1 | <button id="btn">按钮</button> |
this 可以指向事件函数的调用者
操作元素
改变元素的内容
1 | 对象.innerText = ; |
这两个属性也能读取对象内的内容
区别:
- innerText 不能识别 HTML 标签,innerHTML 能识别
- innerText 在读取内容的时候,会自动去除空格和换行,而 innerHTML 会保留
操作元素属性
1 | 对象.属性名 = ; |
也就是可以直接修改
修改表单属性时需要用到表单特有的属性(比如要修改输入框的内容用 inner HTML 就不好使了):
1 | type value checked selected disabled |
样式属性的操作
通过 JS 可以修改元素的大小、颜色、位置等属性。
1 | 1. element.style //行内样式操作 如:div.style.backgroundColor = "purple"; |
element.style
- 属性采用的是驼峰命名法,与CSS不同,如 fontSize backgroundColor
- JS 修改 style 样式时,产生的是行内样式,权重比 CSS 更高
如果要修改的样式比较少,或者功能比较简单的时候,可以这样用
element.className
- 修改元素的类名
- 可以提前把要修改的内容写入 CSS 中,需要改变时应用该 CSS
- 会直接更改类名,也就是覆盖掉以前的类名
- 如果要保留以前的类名,可以在要修改的类名前加上”以前的类名 “(别忘了空格)。(其实原理就是一个元素可以又多个类名)
1 | <style> |
鼠标事件
- 焦点事件
鼠标点击焦点事件 onfocus
失去鼠标焦点事件 onblur
(鼠标焦点是指鼠标点一下,失去焦点是指鼠标点一下其他地方)
1 | var input = document.querySelector("input"); |
- 移入移出事件
鼠标移入事件 onmouseover
鼠标移出事件 onmouseout
1 | window.onload = function() { |
总结

小思想-排他思想
当用 for 循环对多个元素绑定同一事件时,如果想要某一个元素实现某个样式,则可以:
- 清除所有元素的样式
- 给当前的元素设置样式
1 | <button>按钮1</button> |
操作自定义属性
元素自定义属性通常以 data- 开头,如:<p data-time=”20”></p>
- 获取元素的属性
1 | element.属性 |
- 设置元素属性
1 | element.属性 = "值" |
- 移除元素属性
1 | element.removeAttribute('属性') |
- H5 新增获取自定义属性
1 | 如果有一个元素为:<a data-index="1"></a> |
节点操作
简述
一般的,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和 nodeValue(节点值)这三个基本属性
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(文本节点包含文字,空格,换行等)
节点操作的主要对象是元素节点
获取父子节点
- 父级节点
1 | node.parentNode |
- parentNode 返回元素节点的最近的一个父节点(亲爸爸)
- 如果没有找到返回 null
- 子节点
1 | parentNode.childNodes |
- 返回值包含了元素的所有子节点,包括元素节点和文本节点
- 如果只想获取元素节点,则应 专门处理
1 | var ul = document.querySelector('ul'); |
- 子元素节点
1 | parentNode.children |
- children 是一个只读属性,只返回子元素节点,其余节点不返回
- 非标准的,但是得到了很多浏览器的支持
- 第一个/最后一个 子节点
1 | //第一个子节点 |
- 节点包含元素节点和文本节点
- 第一个/最后一个 子元素节点
1 | //第一个子元素节点 |
这两个方法有兼容性问题,ie9 以上才支持
所以可以这样写
1 | //第一个子元素节点 |
获取兄弟关系
- 兄弟节点
1 | //获取元素的下一个兄弟节点,包含所有节点 |
- 兄弟元素节点
1 | //下一个兄弟元素节点 |
- 兼容性问题,ie9 以上才支持
创建节点
1 | document.createElement('tagName') |
- document.createElement() 方法创建由 tagName 指定的 HTML 元素。也称为动态创建元素节点
- 只是创建并没有添加
添加节点
- 在后面追加
1 | node.appendChild(child) |
- 将一个节点添加到指定父节点的子节点列表的末尾,类似于 css 中的 after 伪元素
- 也称为追加元素
- 插入节点
1 | node.insertBefore(child, 指定元素) |
- 将一个节点插入到父节点的指定子节点的前面
删除节点
1 | node.removeChild(childNode) |
复制节点
1 | node.cloneNode() |
- 克隆相当于新建,克隆后需要添加操作
- 如果括号参数为空或者 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
- 如果括号里面为 true,则是深拷贝,既复制节点本身,也复制里面的子节点
三种动态创建元素的区别
document.write()
- 是直接将内容写入页面的内容流,但是会导致页面全部重绘
element.innerHTML
- 是将内容写入某个 DOM 节点,不会导致页面全部重绘
- 创建多个元素效率更高(不要采取拼接字符串,采取数组形式拼接),结构稍微复杂
document.createElement()
- 创建多个元素效率会稍微低一些,但是结构更清晰
DOM 高级
注册事件(绑定事件)
概述
- 给元素添加事件,称为注册事件或者绑定事件
- 注册事件有两种方式:传统方式和方法监听注册方式
- 传统注册方式
- 利用 on 开头的事件,如 onclick
- <button onclick = “alert(‘hi’)”></button>
- btn.onclick = function() { }
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
- 方法监听注册方式
- w3c 标准推荐方式
- addEventListener() 是一个方法
- ie9 之前的 ie 不支持此方法,可使用 attachEvent() 代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
addEventListener 事件监听方式
1 | eventTarget.addEventListener(type, listener, [useCapture]) |
此方法会将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数
同一个元素,同一个事件可以添加多个侦听器
该方法接收三个参数:
- type:事件类型字符串(别忘了加引号),比如 click, mouseover, 等,注意不用带 on
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值
- 当为 true 时,事件处于捕获阶段
- 当为 false 或者 省略 时,事件处于冒泡阶段
1 | btn2.addEventListener('click', function() { |
attachEvent 事件监听方式(了解)
此方法只有 ie9 及以前的浏览器才支持,chrome 等浏览器不支持
1 | eventTarget.attachEvent(eventNameWithOn, callback) |
参数:
- eventTarget:目标对象
- eventNameWithOn:事件类型字符串,比如 onclick, onmouseover,等,要带 on
- callback:事件处理函数
删除事件(解绑事件)
- 传统方式删除事件
.onclick = null;
1 | //如:想让一个div点击一下以后就不能再次点击 |
- 删除方法监听注册的事件
eventTarget.removeEventListener(type, listener, [useCapture])
1 | //如:想让一个div点击一下以后就不能再次点击 |
- 删除 attachEvent 事件
eventTarget.detachEvent(eventNameWithOn, callback)
1 | //如:想让一个div点击一下以后就不能再次点击 |
DOM 事件流
事件发生时会在元素节点之间按照特定的顺序进行传播,这个传播过程叫做 DOM 事件流
- JS 代码只能执行捕获或者冒泡中的一个阶段
- onclick 和 attachEvent 只能得到冒泡阶段
- addEventListener 的第三个参数如果为 true 表示在捕获阶段调用事件处理程序,如果为 false 或 不写则表示在冒泡阶段调用事件处理程序
- 有些事件是没有冒泡的,如:onblur、onfocus、onmouseenter、onmouseleave