Skip to content

第一章、Web APIs介绍

Web APIs是 w3c 组织的标准

Web APIs: javaScript是由 ECMAScript 、BOM、DOM组成的,BOM、DOM 就是Web APIs 是js独有的部分是js的应用

什么是API

APl ( Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

  • 简单理解︰API是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能。

Web API

Web API是浏览器提供的一套操作浏览器功能和页面元素的API( BOM和DOM)。现阶段我们主要针对于浏览器讲解常用的API,主要针对浏览器做交互效果。

第二章、DOM

一、dom简介

文档对象模型(Document Object Model,简称DOM ),是W3C组织推荐的可扩展标记语言(HTML或者XML)的标准编程接口。

  • dom是W3C定义的一系列操作文档页面的API接口通过这些DOM接口可以改变网页的内容、结构和样式

DOM 树

DOM Tree是指在html页面加载的时候,通过浏览器将HTML页面进行解析,并生成的HTML树状结构对应的文档对象和访问方法。

  • 文档 : 一个页面就是一个文档,DOM中使用document表示
  • 元素∶页面中的所有标签都是元素,DOM中使用element表示
  • 节点︰网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
  • DOM 把以上内容都看做对象

DOM的继承关系图

OjKVsS.png

DOM和document对象的理解

  • DOM:文档对象模型(Document Object Model)将页面所有的内容表示为可以修改的对象
    • 浏览器将我们编写在HTML中的每一个元素(Element)都抽象成了一个个对象
    • 所有这些对象都可以通过JavaScript来对其进行访问,那么我们就可以通过JavaScript来操作页面;
    • 所以,我们将这个抽象过程称之为 文档对象模型(Document Object Model)
  • Document节点表示的整个载入的网页,它的实例是全局的document对象:
    • 对DOM的所有操作都是从 document 对象开始的
    • 它是DOM的入口点,可以从document开始去访问任何节点元素;

二、windows全局对象

OLQmon.png

三、Document对象

Document节点表示的整个载入的网页,它的实例是全局的document对象, 在浏览器加载html页面创建的

  • 对DOM的所有操作都是从 document 对象开始的;

  • 它是DOM的 入口点可以从document开始去访问任何节点元素

  • 对于最顶层的html、head、body元素,我们可以直接在 document 对象中获取到:

    • html元素:<html> = document.documentElement

    • body元素:<body> = document.body

    • head元素:<head> = document.head

    • 文档声明:<!DOCTYPE html> = document.doctype

    • 这些都是document对象的属性

      可以查看document对象包含的属性方法

HTMLElement对象常见方法和属性

属性

HTMLElement.tabIndex

tabindex=正值,表示元素是可聚焦的,并且可以通过键盘导航来访问到该元素;它的相对顺序按照tabindex 的数值递增而滞后获焦。

tabindex=负值 (通常是 tabindex=“-1”),表示元素是可聚焦的,但是不能通过键盘导航来访问到该元素,用 JS 做页面小组件内部键盘导航的时候非常有用。

方法

HTMLElement.focus()

该HTMLElement.focus()方法将焦点设置在指定元素上,如果它可以被聚焦的话。焦点元素是默认接收键盘和类似事件的元素。

blur()

控制一个元素失去焦点

click()

控制一个元素被点击了

四、节点Node之间的导航(navigator)

如果我们获取到一个节点(Node)后,可以根据这个节点去获取其他的节点,我们称之为节点之间的导航。

OLQKJ0.png

1、节点之间存在一下关系

  • 父节点:parentNode
  • 前兄弟节点:previousSibling
  • 后兄弟节点:nextSibling
  • 子节点:childNodes
  • 第一个子节点:firstChild
  • 第二个子节点:lastChild

2、元素导航Api

2.1、closest

元素:Element.closest() 方法用来获取:匹配特定选择器且离当前元素最近的祖先元素(也可以是当前元素本身)。如果匹配不到,则返回 null

2.2、contains

Node 接口的 Node.contains() 方法返回一个布尔值,表示一个节点是否是给定节点的后代,即该节点本身、其直接子节点(childNodes)、子节点的直接子节点等。

五、元素(Element)之间的导航(navigator)

OLQuiq.png

1、Element之间存在如下的关系:

  • 父元素:parentElement
  • 前兄弟节点:previousElementSibling
  • 后兄弟节点:nextElementSibling
  • 子节点:children 数组类型
  • 第一个子节点:firstElementChild
  • 最后子节点:lastElementChild

六、表格(table)元素的导航(navigator)

  • <table> 元素支持 (除了上面给出的,之外) 以下这些属性:

    • table.rows<tr> 元素的集合;
    • table.caption/tHead/tFoot — 引用元素 <caption><thead><tfoot>
    • table.tBodies<tbody> 元素的集合 需要用[]取元素;
  • <thead><tfoot><tbody> 元素提供了 rows 属性:

    • tbody.rows — 表格内部 <tr> 元素的集合;
  • <tr>

    • tr.cells — 在给定 <tr> 中的 <td><th> 单元格的集合;

    • tr.sectionRowIndex — 给定的 <tr> 在封闭的 <thead>/<tbody>/<tfoot> 中的位置(索引);

      就是在tbody里面开始计算索引

    • tr.rowIndex — 在整个表格中 <tr> 的编号(包括表格的所有行);

      就是在当前行的索引

  • <td><th>

    • td.cellIndex — 在封闭的 <tr> 中单元格的编号。

      在当前行计算单元格的索引

七、表单(form)元素的导航(navigator)

document 对象当中可以同伙forms属性可以直接获取html文档中的所有form节点元素

  • <form> 元素可以直接通过document来获取:document.forms

    js
    let formEl = document.forms[0];
    let formEl = document.forms[0];
  • <form>元素中的内容可以通过elements来获取:form.elements

    js
    formEl.elements[3].style.backgroundColor = "red"
    formEl.elements[3].style.backgroundColor = "red"
  • <form> 元素可以通过设置表单子元素name来获取它们获取元素: form.子元素的name值

    html
    <form action="">
      <input name="inpValue" type="text">
      </select>
    </form>
    <script>
        //获取form的属性的方式
        formEl.inpValue.setAttribute("value","jfsljfdljf")
    </script>
    <form action="">
      <input name="inpValue" type="text">
      </select>
    </form>
    <script>
        //获取form的属性的方式
        formEl.inpValue.setAttribute("value","jfsljfdljf")
    </script>

1、清空form表单

  • formEl.reset() 清空form表单
  • fileEl.value = "" 清空file 对象

八、获取元素的方法(6个)

  • 目前最常用的是querySelector和querySelectAll;
  • getElementById偶尔也会使用或者在适配一些低版本浏览器时;
方法名搜索方式是否可以在元素上调用是否是实时的
querySelector()CSS-selector- Css选择器 返回的是节点对象yes-
querySelectorAll()CSS-selector- Css选择器yes-
getElementById()id--
getElementByName()name-yes
getElementByTagName()tag or '*'yesyes
getElementByClassName()classyesyes
Element.closest()参数选择器,Element.closest() 方法用来获取:匹配特定选择器且离当前元素最近的祖先元素(也可以是当前元素本身)。如果匹配不到,则返回 nullyes
  1. 就是id 对于在元素上的调用和实时都是不支持的
  2. 实时的除了name,和select都可以一共6个

九、节点的属性(9个)

不同的节点类型有可能有不同的属性, 主要记节点共有的属性

1、nodeType类型:138

  • nodeType 属性提供了一种获取节点类型的方法;

  • 数值型值(numeric value);

  • 常见节点属性

    常量描述
    Node.ELEMENT_NODE1一个元素的节点,例如<p> 和<div>
    Node.TEXT_NODE3Element 或者 Attr 中实际的文字
    Node.COMMENT_NODE8一个 Comment 节点
    Node.DOCUMENT_NODE9一个 Document 节点
    Node.DOCUMENT_TYPE_NODE10描述文档类型的 DocumentType 节点。例如<!DOCTYPE html> 就是用于HTML5的。

    其他类型可以查看MDN文档 >

2、nodeName/tagName属性

  • nodeName:获取node节点的名字;

  • tagName:获取元素的标签名字 返回的是大写标签名

  • tagName 和 nodeName 之间的区别

    • tagName 属性仅适用于 Element 节点,非元素节点获取不到undefined

      非元素节点没有标签名,所以获取不到

    • nodeName 是为任意 Node 定义的

      • 对于元素,它的意义与 tagName 相同,所以使用哪一个都是可以的;
      • 对于其他节点类型(text,comment 等),它拥有一个对应节点类型的字符串;
      • 例如:注释:返回一个 #comment 字符串,换行符和文本的话返回一个 #text 字符串

3、nodeValue/data

都是用来获取非元素节点的内容,例如: text文本,comment注释 等...内容

4、innerHTML、textContent、outerHTML、innerText

  1. innerText/textContent可读可写rw

    1. 这两个节点属性都是用来获取后代元素的文本

    2. 写入时都不会做html字符串标签的解析文本内容会替换所有子元素

    3. 区别:textContent 不会解析内容直接显示(用的比较多,性能稍微好一点) ,innerText 浏览器会解析一下

      innerText 就是在浏览器页面显示什么样打印出来的就是什么样

      textContent 就是在代码中文本怎么显示的,它打印出来就是什么样

  2. innerHTML,可读可写rw

    • 获取选中元素下面的完整的代码内容包括标签
    • 写入的时候会解析html标签字符串文本内容会替换所有子元素
    • 缺点:js进行解析字符串之后在解析标签,比较耗费性能,会直接替换所有子元素
  3. outerHTML,可读可写rw

    • 重点outerHTML 不适用于任何已从没有父级的 DOM分离的元素,或 HTML 标记(预计将是根)。

      js
      //例如 创建的div 没有父级因此不能替换本身
      var dom = document.createElement('div');
      	dom.outerHTML = str;
      //例如 创建的div 没有父级因此不能替换本身
      var dom = document.createElement('div');
      	dom.outerHTML = str;
    • 获取选中元素及包含的完整代码内容,包含自身元素

    • 写入的时候会解析html标签字符串 ,同时替换当前元素

5、元素的全局属性补充

  • hidden属性:也是一个全局属性,可以用于设置元素隐藏。

    就是相当于给当前元素添加了 display: none

6、dom元素还有其他属性

  • value

    • <input><select><textarea>HTMLInputElementHTMLSelectElement......)的 value

    • value属性是针对input元素的
  • herf

    • <a href="...">HTMLAnchorElement)的 href
  • id

    • 所有元素(HTMLElement)的 “id” 特性(attribute)的值。

十、元素的属性property 和特性attribute

浏览器在解析HTML元素时,会将对应的attribute也创建出来放到对应的元素对象上。

比如id、class就是全局的attribute,会有对应的id、class属性

比如href属性是针对a元素的,type、value属性是针对input元素的

  • 两个都可以自定义属性

1、Attribute的操作(5个)

对于所有的attribute访问都支持如下的方法:我们称attribute为特性为了区分porperty

  1. el.hasAttribute(name) — 检查是否存在对应的特性。
  2. el.getAttribute(name) — 获取这个特性值。
  3. el.setAttribute(name, value) — 设置这个特性值。
  4. el.removeAttribute(name) — 移除这个特性。
  5. el.attributesattr对象的集合,具有namevalue属性;

1.1、attribute具备以下特征

  • 它们的名字是大小写不敏感的(id 与 ID 相同)。 属性的大小不敏感
  • 它们的值总是字符串类型的。 属性的值总是字符串类型

2、attribute的分类

  • 自定义属性会放到 html 元素的标签上面

  • 标准的attribute:Attribute就是DOM节点自带属性,或者在标签元素上或者 attriabute 自定义的属性

    标准属性:HTML标准制定的属性,就是标准属性 ,例如:我们在HTML中常用的id,class,src,title,alt等。

    1. 标准的attribute,浏览器在解析HTML元素时 在DOM对象上 创建与其对应的property/attribute属性,修改properity的话会相互影响getAttribute的值
  • 非标准的attribute:某些attribute属性是自定义的,比如abc、age、height等;

    1. 非标准的attribute 浏览器在解析HTML元素时 不会 在DOM对象上 创建与其对应的property/attrbute属性 ,这样的话就 不会setAttribute 修改的属性值 相互影响

3、property

property 是创建dom的时候附加的一些内置属性,顺便将标准属性也添加了进来,所以会和 attriabute 相互影响 例如:style,className,nodeType,data,nodeName。

  • 也可以自定义属性过会放到dom元素对象的上面

  • 而Property则是这个DOM元素作为对象,其附加的属性或者内容,

  • 由于构建dom的时候将html的一些标准属性附加到了property上面,所以修改标准属性的时候会相互影响

    所以:添加标准属性的时候, 也会添加到 html 元素的标签上

  • 可以添加标准属性但是不能删除

4、properity和attribute的区别

  1. attribute 添加属性会添加到html上,property 添加属性会添加到内置dom对象中

    所以:properity 不能修改setAttribute 设置的非标准属性,setAttribute 可以修改所有属性

  2. 元素标签中设置Boolean属性的时候可以不用写值,但是在使用getAttribute 获取Boolean值属性的时候 返回的空字符串

  3. properity 推荐使用property的方式 获取时会获取到值,默认情况下是有类型的

  4. 但是input的value修改只能通过attribute的方法

html
<body>
  <input type="checkbox" checked >
</body>
<script>
  console.log(document.body.children[1].getAttribute("checked"));
    //output ""
  console.log(document.body.children[1].checked);
    //output true
</script>
<body>
  <input type="checkbox" checked >
</body>
<script>
  console.log(document.body.children[1].getAttribute("checked"));
    //output ""
  console.log(document.body.children[1].checked);
    //output true
</script>
  • 总结:获取元素使用 properity,对于布尔属性 会有自己的类型,设置修改元素的时候使用setAttribute(), 因为所有元素都属性都可以被修改

十一、JavaScript动态修改样式(2个)

  • 有时候我们会通过JavaScript来动态修改样式,这个时候我们有两个选择:

    • 选择一:在CSS中编写好对应的样式,动态的添加class
    • 选择二:动态的修改style属性
  • 开发中如何选择呢?

    • 在大多数情况下,如果可以动态修改class完成某个功能,更推荐使用动态class;
    • 如果对于某些情况,无法通过动态修改class(比如精准修改某个css属性的值),那么就可以修改style属性;

11.1、动态的添加class

1、className

元素的class attribute,对应的property并非叫class,而是className:

  • 通过修改 className 给元素添加class属性来动态的添加元素的样式
  1. 这是因为JavaScript早期是不允许使用class这种关键字来作为对象的属性,所以DOM规范使用了className来作为添加修改元素class属性值的接口

  2. 虽然现在JavaScript创建对象属性时已经没有这样的限制,但是并不推荐,并且依然在使用className这个名称

js
document.querySelector("div").addEventListener("click",function (){
  document.body.children[0].className = "box"
})
document.querySelector("div").addEventListener("click",function (){
  document.body.children[0].className = "box"
})
注意:这里使用className 添加的class属性会覆盖 元素上面原有的class属性所以不建议使用,建议使用classList

2、classList(4个) 可迭代对象

如果我们需要添加或者移除单个的class,那么可以使用classList属性

  • 他会添加到html元素的class集合里面,前面自动添加空格,不会覆盖
  • classList 是一个可迭代对象 可以使用for...of
    • elem.classList.add (class) :添加一个类
    • elem.classList.remove(class):添加/移除类。
    • elem.classList.toggle(class) :如果类不存在就添加类,存在就移除它。
    • elem.classList.contains(class):检查给定类,返回 true/false。

11.2、动态的修改style属性(3种)

如果需要单独修改某一个CSS属性,那么可以通过style来操作

  • 元素对象当中的 style 属性是个对象 里面有很多的css属性
  • 如果我们将设置为空字符串,那么会使用CSS的默认样式
  1. 方法一 setProperty 修改style对象属性的属性值

    js
    //在元素对象中修改style对象属性的属性值
    document.body.style.setProperty("color","red")
    //在元素对象中修改style对象属性的属性值
    document.body.style.setProperty("color","red")
  2. 方法二 . 修改style对象属性的属性值

    js
    //在元素对象中修改style对象属性的属性值
    document.body.style.color = "red"
    //在元素对象中修改style对象属性的属性值
    document.body.style.color = "red"
  3. 方法三 cssText 替换style内联样式表的字符串

    js
    //这里会覆盖原有的 内联样式表,所以不常用
    document.documentElement.style.cssText = "color: red"
    //这里会覆盖原有的 内联样式表,所以不常用
    document.documentElement.style.cssText = "color: red"

注意:如果style对象的css属性等于空字符串的情况下使用的是默认的值

元素style的读取 getComputedStyle() 全局方法

对于内联样式,是可以通过style.*的方式读取到,但是对于style、css文件中的样式,是读取不到的

  • 我们可以通过getComputedStyle的全局函数来实现:

  • 还可以用来获取pseudo的样式 第二个参数 字符串类型

    js
    //还可以用来获取pseudo的样式
    var boxEl = getComputedStyle(document.querySelector(".box")).width
    console.log(boxEl);
    //还可以用来获取pseudo的样式
    var boxEl = getComputedStyle(document.querySelector(".box")).width
    console.log(boxEl);
  • 不选中属性的话返回的是style对象的属性

  • 返回的值都是只读,不可以修改

十二、创建元素

document.createElement(tag)

十三、对元素的操作方法

1、新的插入元素方法(5个)

DOMString 对象等价为 Text 节点。也就是可以插入字符串,但是也不会解析标签字符串,没有返回值

  • node代表节点,节点=元素|txt|注释。但通常情况下只在元素下调用
  1. node.append(...nodes or strings) 和 node.appendChild 作用是一样的

    在 当前 node内部 末尾 插入节点或字符串

  2. node.prepend(...nodes or strings)

    在 当前 node内部 开头 插入节点或字符串

  3. node.before(...nodes or strings)

    在 当前 node 前面 插入节点或字符串

  4. node.after(...nodes or strings)

    在 当前 node 后面 插入节点或字符串

  5. node.replaceWith(...nodes or strings)

    将 当前 node 替换为指定的节点或字符串。

3、老的插入元素方法(4个) 参数排列,新老

只接受节点类型,返回值是新添加的节点

  • el.appendChild(childEl):

    在el元素 "内" 最后位置添加一个子元素

  • el.insertBefore(newChild, oldChild):

    在el的元素 "内",oldChild 前面插入 newChild;指定的元素前面的追加

  • el.replaceChild(newChild, oldChild):

    newChild 替换 el 元素 "内" 的, 子元素 oldChild

  • el.removeChild(childEl):

    移除 el 元素内指定的子元素

4、元素的移除和克隆(2个)

  1. 调用元素本身的remove方法:

    element.remove()

  2. 调用节点本身的cloneNode方法:

    node.cloneNode(boolean)

    • 参数deep(深度)
    • 深度拷贝会将当前节点元素下所有后代元素一起拷贝
    • 注意:cloneNode,是拷贝节点这就意味这,也可以拷贝文本节点或者注释节点

十四、元素的大小、滚动(14个)

1、client(4个):

注意:不包含滚动条,滚动条默认19px

特点:含padding,不含滚动条

  • clientWidth

    • 重点:如果有 over-flow: hidden 的时候,clientWidth 是可显示的宽度
    • 通常搭配 transfrom 移动时使用

    就像背景图一样,包含padding,但是不包含滚动条

  • clientHeight

    内容高度+padding

  • clientTop

    顶部border的宽度

  • clientLeft

    左侧border的宽度

2、offset(4个) 只读属性

特点:border-box

  • offsetWidth:元素完整的宽度

    不包括外边距

  • offsetHeight:元素完整的高度

    不包括外边距

  • offsetLeft:距离offsetParent元素左边缘的距离

    这里使用 translate的时候 offsetLeft失效

    相对于祖先定位元素或者 table,td,th,body

  • offsetTop:距离offsetParent元素上边缘的距离

    这里使用 translate的时候 offsetLeft失效

    相对于祖先定位元素或者 table,td,th,body

offset

  • offset可以得到任意样式表中的样式值offset系列获得的数值是没有单位的
  • offsetWidth包含padding+border+width
  • offsetWidth等属性是只读属性,只能获取不能赋值
  • 所以,我们想要获取元素大小位置,用offset更合适

style

style只能得到行内样式表中的样式值style.width获得的是带有单位的字符串 style.width获得不包含padding和border的值style.width是可读写属性,可以获取也可以赋值所以,我们想要给元素更改值,则需要用style改变

3、scroll(4个)

  • scrollHeight:当前元素整个可滚动的区域高度
  • scrollTop:滚动时超出上边缘的距离
  • scrollBy(x, y):相对于滚动原点,滚动到指定位置
  • scrollTo(x, y):相对于页面绝对位置,滚动到指定位置 比较scrollTop只能是y轴

4、getClientRects和getBoundingClientRect()区别

迷一样的两个方法

getBoundingClientRect()用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。getBoundingClientRect()是DOM元素到浏览器可视范围的距离(不包含页面看不见的部分)。该函数返回一个Object对象,该对象有6个属性:top, left, bottom, right, width, height;这里的top、left和css中的理解很相似,width、height是元素自身的宽高,但是right,bottom和css中的理解有点不一样。right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。

虽然看上面说还是不太明确

js
console.log("right",containerEl.getClientRects()[0].right == containerEl.getBoundingClientRect().right);
  console.log("top",containerEl.getClientRects()[0].top == containerEl.getBoundingClientRect().top);
  console.log("left",containerEl.getClientRects()[0].left == containerEl.getBoundingClientRect().left);
  console.log("bottom",containerEl.getClientRects()[0].bottom ==containerEl.getBoundingClientRect().bottom);
/*
output
right true
top true
left true
bottom false
*/
console.log("right",containerEl.getClientRects()[0].right == containerEl.getBoundingClientRect().right);
  console.log("top",containerEl.getClientRects()[0].top == containerEl.getBoundingClientRect().top);
  console.log("left",containerEl.getClientRects()[0].left == containerEl.getBoundingClientRect().left);
  console.log("bottom",containerEl.getClientRects()[0].bottom ==containerEl.getBoundingClientRect().bottom);
/*
output
right true
top true
left true
bottom false
*/
  • 就是这样了 getClientRectsgetBoundingClientRect(),看效果是处理bottom不一样剩下都一样

  • 在就是getClientRects返回的是一个集合,也不知道为什么是集合

  • getBoundingClientRect方法的 top、left、bottom、top的图

OLMjqH.png

  • 用到的时候在说吧

十五、window的大小、滚动(5个)

1、window的width和height(3个)

  • innerWidth、innerHeight

    获取window窗口的宽度和高度(包含滚动条)

  • outerWidth、outerHeight

    获取window窗口的整个宽度和高度(包括调试工具、工具栏)

  • documentElement.clientHeight、documentElement.clientWidth:注意不包含滚动条

    注意:不包含滚动条,滚动条默认19px 也可以说clientWidth是窗口不包含滚动条的宽高,因为**设置html高度不会影响clientWidth/Height的大小****

    会影响的是offsetWidth/Height的大小

    获取html的宽度和高度 documentElement.clientWidthinnerWidth的区别就是(不包含滚动条)

2、window的滚动位置:(2个只读属性)

  • scrollX:X轴滚动的位置(别名pageXOffset)对比scrollTop的区别时 scrollx 是只读的

    • 别名 pageXOffset
  • scrollY:Y轴滚动的位置(别名pageYOffset

    • 别名 pageYOffset

    注意:window没有scrollTop属性只有scrollX同样作用

  • 也有提供对应的滚动方法:参数是数值没有px

    • 方法 scrollBy(x,y) :将页面滚动至 (x, y)位置; 相对元素的当前位置

      就是在当前位置上面累加

    • 方法 scrollTo(pageX,pageY) 将页面滚动至 绝对坐标相对于页面;

十六、javaScript事件

1、事件监听

1.1、添加事件监听(3)

  1. 事件监听方式一:在HTML标签中直接监听(很少使用);
  2. 事件监听方式二:DOM属性,通过元素的on来监听事件;
  3. 事件监听方式三:通过 EventTarget 中的 addEventListener 来监听;

1.2、移除事件监听

换个事件总线一样,需要传入相同的函数对象,在可以取消,否则无效

js
const myCallback = () => {
  console.log('clicked!');
};

document.getElementById('button').addEventListener('click', myCallback);
document.getElementById('button').removeEventListener('click', myCallback);

//移除所有click事件
const listeners = element._events.click;
for (let i = 0; i < listeners.length; i++) {
    element.removeEventListener("click", listeners[i]);
}
const myCallback = () => {
  console.log('clicked!');
};

document.getElementById('button').addEventListener('click', myCallback);
document.getElementById('button').removeEventListener('click', myCallback);

//移除所有click事件
const listeners = element._events.click;
for (let i = 0; i < listeners.length; i++) {
    element.removeEventListener("click", listeners[i]);
}

1.3、onclick、直接监听和 addEventListener监听事件的区别

  1. .onclickaddEventListener 的区别,加载完成时候页面显示的元素可以用 on,也可以用 click,但是页面加载完成之后后期再追加的元素只能用on

    js
    // append 这种操作不会让元素时区监听,remove()掉元素,监听才会直接断开,这样的情况无论是那种监听方式都是一样的效果
    boxEl.append(textEl)
    // append 这种操作不会让元素时区监听,remove()掉元素,监听才会直接断开,这样的情况无论是那种监听方式都是一样的效果
    boxEl.append(textEl)
  2. HTML直接监听,这种方式在同步渲染的时候才会有效

2、事件流

事件流:当一个HTML元素产生一个事件时,该事件会在元素节点与根节点之间的路径传播,路径所通过的节点都会接收到该事件,这个传播的过程叫做DOM事件流

2.1、事件流的传播方式

  1. 事件冒泡:默认情况下事件是从最内层span 向外依次传递的顺序,这个顺序我们称之为事件冒泡(Event Bubble)

  2. 事件捕获:还有另外一种监听事件流的方式就是从外层到内层body -> span),这种称之为事件捕获(Event Capture)

为什么会产生两种不同的处理流呢

这是因为早期浏览器开发时,不管是IE还是Netscape公司都发现了这个问题; 但是他们采用了完全相反的事件流来对事件进行了传递 也是历史的原因两种方式都保留了下来; IE采用了事件冒泡的方式,Netscape采用了事件捕获的方式;

js中默认的事件流传播顺序是冒泡

OL1oIs.png

2.1.1.事件捕获和冒泡的过程

如果我们都监听,那么会按照如下顺序来执行:

  • 捕获阶段(Capturing phase): 阶段 1 事件(从 Window)向下走近元素。
  • 目标阶段(Target phase):阶段 2 事件到达目标元素。 就是被点击
  • 冒泡阶段(Bubbling phase):阶段 3 事件从元素上开始冒泡
2.1.2.监听事件的捕获和冒泡
  • 常用的还是事件冒泡
js
//修改事件流的处理方式,addEventListener传入的第三个boolean类型参数 设置伪true修改为事件捕获
  spanEl.addEventListener("click",function (e) {
    console.log("span事件捕获");
  },true)
//修改事件流的处理方式,addEventListener传入的第三个boolean类型参数 设置伪true修改为事件捕获
  spanEl.addEventListener("click",function (e) {
    console.log("span事件捕获");
  },true)

事实上,我们可以通过event对象eventPhase属性来获取当前的阶段:

  • eventPhase 获取当前事件流阶段,Number类型
    1. capture 阶段 1 事件流被捕获的时侯触发的事件
    2. target 阶段 2 就是被点击元素发生的事件
    3. bubbling 阶段 3 事件流向外传递冒泡的时候触发的事件

OL17in.png

2.2、重要 事件对象

event对象会在传入的事件处理(event handler)函数回调时,被系统传入,我们可以在回调函数中拿到这个event对象;

2.2.1、常见属性(8个)
  1. type:事件的类型;

  2. target:当前事件发生的元素(重要);

  3. currentTarget:当前处理事件的元素(重要);

    target 和 currentTarget的区别

    在父级绑定事件的前提下,就是父元素绑定了事件,然后点击了子元素这样的情况下

    targent 代表点击的元素 currentTarget代表的是事件绑定的元素

  4. eventPhase:事件所处的阶段;

位置属性 4类

  1. offsetXoffsetY:事件发生在元素内鼠标点击的位置;
  2. clientXclientY:事件发生在客户端内或者window窗口鼠标点击的位置;
  3. pageXpageY:接口返回的相对于整个文档的x y,获取的值和 clientX 相等,但是应该有区别
  4. screenXscreenY:事件发生相对于屏幕点击的位置;
2.2.2、常见的方法(2个)
  1. event.preventDefault:取消事件的默认行为;
  2. event.stopPropagation:阻止事件的进一步传递(冒泡或者捕获都可以阻止);
2.2.3、事件处理中的this

在事件函数中,我们也可以获取thisthis的指向的是currentTarget对象,就是当前绑定事件的对象

2、事件委托(event delegation)重要

  • 事件委托就是,当一个html元素产生了一个事件,元素本身不做处理,而交由事件传播路径上的的其他元素来监听处理

事件冒泡在某种情况下可以帮助我们实现强大的事件处理模式 – 事件委托模式

元素产生事件的时候,通过事件流的传播方式,监听到父元素或者子元素的的事件;

  1. 因为当子元素被点击时,父元素可以通过冒泡可以监听到子元素的点击;不添加事件的时候也会冒泡
  2. 并且可以通过 event.target 获取到当前监听的元素;
  3. 事件委托和事件冒泡的关系也可以这么理解,当子元素点击冒泡的时候,发生事件的父元素监听到了子元素的冒泡 ,所以事件阶段是3,也就是冒泡阶段

2.1、事件委托的标记

某些事件委托可能需要对具体的子组件进行区分,这个时候我们可以使用data-*对其进行标记:

2.2、事件委托 排他 经典案例(重点)

html
<body>
  <div class="box">
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
    </ul>
  </div>
</body>
<script>
  var flag = null;
  document.querySelector(".box ul").addEventListener("click", function() {
    if(this !== event.target){
      flag && flag.style.setProperty("color","")
      event.target.style.color = "red"
      flag = event.target;
    }
  })
</script>
<body>
  <div class="box">
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
    </ul>
  </div>
</body>
<script>
  var flag = null;
  document.querySelector(".box ul").addEventListener("click", function() {
    if(this !== event.target){
      flag && flag.style.setProperty("color","")
      event.target.style.color = "red"
      flag = event.target;
    }
  })
</script>

2.3、获取元素索引案例

js
//通过获取元素的索引进行多个元素同步处理
currentIndex = Array.from(this.children).findIndex(function(el, index, arr) {
          if(event.target === el){
            return el
          }
        })
//通过获取元素的索引进行多个元素同步处理
currentIndex = Array.from(this.children).findIndex(function(el, index, arr) {
          if(event.target === el){
            return el
          }
        })

3、事件分发EventTarget类

EventTarget类 是一个 DOM 接口,由可以接收事件、并且可以创建侦听器的对象实现。

  • 所有的节点、元素都继承自EventTarget

  • 事实上Window也继承自EventTarget

  • EventTarget是一个DOM接口,主要用于添加、删除、派发Event事件

3.1、EventTarget常见的方法(3个)

window对象也继承这个类EventTarent

  1. addEventListener:注册某个事件类型以及事件处理函数;

  2. removeEventListener:移除某个事件类型以及事件处理函数;

  3. dispatchEvent:派发某个事件类型到EventTarget上; 只能作用在windwos上

    使用场景还没有想好,相当于可以批量处理一堆函数,但是应该都是同步的,慎重使用

    应该是给谁派发谁才能监听到;这样应该就不能批量处理了 不知道使用场景

3.2、事件的派发

事件总线的一种实现

3.2.1、自定义事件的使用
  • 使用方法一
js
var btnEl = document.querySelector(".btn")
  //创建自定义事件对象 ,detail是自定义的参数,最后会放到事件函数中的event对象中
  var customEv = new CustomEvent("wyn", {detail: "zhangsan"})

  btnEl.addEventListener("click", function (e) {
    this.dispatchEvent(customEv)
  })

//给谁自定义的事件,谁就能调用
  btnEl.addEventListener("wyn",function (e) {
    console.log(e.detail);
  })
var btnEl = document.querySelector(".btn")
  //创建自定义事件对象 ,detail是自定义的参数,最后会放到事件函数中的event对象中
  var customEv = new CustomEvent("wyn", {detail: "zhangsan"})

  btnEl.addEventListener("click", function (e) {
    this.dispatchEvent(customEv)
  })

//给谁自定义的事件,谁就能调用
  btnEl.addEventListener("wyn",function (e) {
    console.log(e.detail);
  })
  • 使用方法二

    js
    var btnEl = document.querySelector(".btn")
    
      btnEl.addEventListener("click", function (e) {
    	//Event对象可以定义 初始化数据,是否冒泡等等
      btnEl.dispatchEvent(new Event("wyn"))
    
      })
    	//给谁自定义的事件,谁就能调用
      btnEl.addEventListener("wyn",function(){
        
        console.log("first")
      })
    var btnEl = document.querySelector(".btn")
    
      btnEl.addEventListener("click", function (e) {
    	//Event对象可以定义 初始化数据,是否冒泡等等
      btnEl.dispatchEvent(new Event("wyn"))
    
      })
    	//给谁自定义的事件,谁就能调用
      btnEl.addEventListener("wyn",function(){
        
        console.log("first")
      })
3.2.2、自动触发默认事件
js
var event = new MouseEvent('click')
  //触发boxEl的点击事件,其他事件查看 MDN 文档
  boxEl.dispatchEvent(event)
  //也可以使用
  var event = new Event('resize')
  window.dispatchEvent(event)
var event = new MouseEvent('click')
  //触发boxEl的点击事件,其他事件查看 MDN 文档
  boxEl.dispatchEvent(event)
  //也可以使用
  var event = new Event('resize')
  window.dispatchEvent(event)

4、事件丢失

场景: html 页面使用模板引擎的时候,当动态渲染的 html 元素添加事件的时候,事件可能会丢失

  1. 当第一次动态渲染弹框的时候无法监听事件时,将 .onclick() 切换 ``addEventListener 进行监听

  2. 但是当你重复渲染 html,原本添加的事件也会重复渲染的html元素消失

    解决:在重复渲染html,之后在重新添加事件

  • 所以当事件失效的时候,要注意查看代码是否有重复渲染的操作

十七、定时器

大多数运行环境都有内置的调度程序,并且提供了这些方法:

  • 目前来讲,所有浏览器以及 Node.js 都支持这两个方法;

1、setTimeout

setTimeout 允许我们将函数推迟到一段时间间隔之后再执行。

  • 参数:

    1. func|code:想要执行的函数或代码字符串。

      • 一般传入的都是函数,由于某些历史原因,支持传入代码字符串,但是不建议这样
    2. delay:执行前的延时,以毫秒为单位(1000 毫秒 = 1 秒),默认值是 0

    3. arg1,arg2...:要传入被执行函数(或代码字符串)的参数列表;

js
var timer = setTimeout((arg1, arg2,...) => {
    console.log(arg1 ,arg2)
  }, delay, arg1, arg2);
var timer = setTimeout((arg1, arg2,...) => {
    console.log(arg1 ,arg2)
  }, delay, arg1, arg2);
  • 取消定时器:clearTimeout:取消 setTimeout 的定时器;

2、setInterval

etInterval 方法和 setTimeout 的语法相同: 不过与 setTimeout 只执行一次不同,setInterval 是每间隔给定的时间周期性执行;

setInterval 允许我们重复运行一个函数,从一段时间间隔之后开始运行,之后以该时间间隔连续重复运行该函数。

  • clearInterval:取消setInterval的定时器;

    setInterval也会返回一个“定时器标识符(timer identifier)”,我们可以通过clearInterval来取消这个定时器。

十八、 javaScript事件的监听方式

事件就是,捕捉Web页面和用户之间进行交互的过程:; 浏览器需要搭建一条JavaScript代码和事件之间的桥梁;

注意事项

  1. 使用addEventlinsenter的时候 事件名称前后注意 不要有空格否则失效

当某个事件发生时,让 JavaScript 可以相应(执行某个函数),所以我们需要针对事件编写处理程序(handler);

1、鼠标事件(10个)

放大镜移动的公式: 小图片移动的距离/小图片最大移动距离 = 大图片移动的距离/ 大图片最大移动距离

属性描述
click当用户点击某个对象时调用的事件句柄。
contextmenu在用户点击鼠标右键打开上下文菜单时触发
dblclick当用户双击某个对象时调用的事件句柄。
mousedown鼠标按钮被按下。
mouseup鼠标按键被松开。
mouseover鼠标移到某元素之上。(支持冒泡
mouseout鼠标从某元素移开。(支持冒泡
mouseenter当鼠标指针移动到元素上时触发。(不支持冒泡
mouseleave当鼠标指针移出元素时触发。(不支持冒泡
mousemove鼠标被移动。

1.1、mouseenter和mouseover的区别

  1. mouseenter 和 mouseleave:不支持冒泡

    进入子元素依然属于在该元素内,没有任何反应

  2. mouseover 和 mouseout:支持冒泡

    进入元素的子元素时

    1. 父元素的先mouseover->mouseout到子元素
    2. 再调用子元素的mouseover
    3. 因为支持冒泡,所以会将mouseover传递到父元素中;
    • 离开的时候也是一样,子元素掉用一次离开, 父元素在调用一次 over 和 out

1.2、mouseenter和mouseover注意事项

  • mouseenter,没有冒泡事件,所以当触碰子元素的时候父元素也能监听到,就像css hover状态
  • mouseover,有冒泡事件,当子元素重合或者超出父元素的时候,不会触发父元素,但是会冒泡到父元素
    1. 给父元素绑定 mouseenter 事件之后,触碰子元素也是父元素的范围 target也是父元素,
    2. over是触碰到谁target就是谁,enter target 都是 currentTarget
    3. 但是over不一样,就是当触碰子元素的时候中间的元素并没有,监听事件所以 target 不会是中间元素。就是触碰到谁target就是谁

2、键盘事件:(3个)

属性描述
onkeydown某个键盘按键被按下。
onkeypress发生在文本被输入
onkeyup某个键盘按键被松开。

我们可以通过keycode来区分按下的键:

  1. e.code:“按键代码”(KeyAArrowLeft 等),特定于键盘上按键的物理位置。
  2. e.key:字符(Aa 等),对于非字符(non-character)的按键,通常具有与 code 相同的值。)
  3. e.keyCode:按键代码
js
/**
   * 顶部栏全局搜索*/
  $("#header-searchProduct").on("keydown", function (e) {
    if (e.keyCode === 13) {
      console.log("用户按下enter键", $.trim(this.value), e.code, e.key, e.keyCode);
    }
  })
/**
   * 顶部栏全局搜索*/
  $("#header-searchProduct").on("keydown", function (e) {
    if (e.keyCode === 13) {
      console.log("用户按下enter键", $.trim(this.value), e.code, e.key, e.keyCode);
    }
  })

3、表单(form)元素事件(6个)

重点:所有的表单元素都应该用form包裹,之后用 submit 事件提交,这样当回车的时候会自动触发submit,可以防止使用keydown事件输入英文时由于使用的时中文输入法需要回车的情况误触发事件

属性描述
onchange该事件在表单元素的内容改变时触发( <input>, <keygen>, <select>, 和 <textarea>)
oninput元素获取用户输入时触发
onfocus元素获取焦点时触发
onblur元素失去焦点时触发
onreset表单重置时触发
onsubmit表单提交时触发

4、CSS 事件:

  • transitionend —— 当一个 CSS 动画完成时。

5、文档加载事件(2个)

5.1、DOMContentLoaded:

MDN文档: 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完全加载。

浏览器已完全加载 HTML,并构建了 DOM 树,但像 <img> 和样式表之类的外部资源如css可能尚未加载

DOMContentLoaded的触发时机是:加载完页面,解析完所有标签(不包括执行CSS和JS),但是JS的执行,需要等待位于它前面的CSS加载(如果是外联的话)、执行完成,因为JS可能会依赖位于它前面的CSS计算出来的样式。所以:

  • 如果页面中没有script标签,DOMContentLoaded事件并没有等待CSS文件、图片加载完成。

  • 如果页面中静态的写有script标签,DOMContentLoaded事件需要等待JS执行完才触发。而且script标签中的JS需要等待位于其前面的CSS的加载完成。

    因为 script 标签是dom

js
document.addEventListener("DOMContentLoaded", (event) => {
  console.log("DOM 完全加载和解析");
});
document.addEventListener("DOMContentLoaded", (event) => {
  console.log("DOM 完全加载和解析");
});

5.2、load:

浏览器不仅加载完成了 HTML,还加载完成了所有外部资源:图片,css样式等。

事件类型

js
window.addEventListener("load", (event) => {
  console.log("page is fully loaded");
});
window.addEventListener("load", (event) => {
  console.log("page is fully loaded");
});

6、滚轮事件wheel

7、页面可见事件onvisibilitychange 事件

  • document.visibilityState: 页面可见状态属性
    • hidden
    • visible

当页面可见和不可见的时候时候触发

场景:

  1. 切换应用

  2. 最小化

应用场景:

轮播图 使用traniform 来移动图片的时候,进行切换后台的时候tranisrom不会运行,在切回来的时候会快速的移动

  • focus事件并不适用,因为在点击导航栏的时候也算失去焦点

第三章、BOM

一、认识BOM

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

简称 BOM,由浏览器提供的用于处理文档(document)之外的所有内容的其他对象;

BOM提供了独立于内容 而与浏览器窗口进行交互的对象;

比如navigator、location、history等对象;

  • JavaScript有一个非常重要的运行环境就是浏览器
  • 而且浏览器本身又作为一个应用程序需要对其本身进行操作;
  • 所以通常浏览器会有对应的对象模型(BOM,Browser Object Model);
  • 我们可以将BOM看成是连接JavaScript脚本与浏览器窗口的桥梁;

1、BOM主要包括一下的对象模型:5个

  1. window:包括全局属性、方法,控制浏览器窗口相关的属性、方法;
  2. location:浏览器连接到的对象的位置(URL);
  3. history:操作浏览器的历史;
  4. navigator:用户代理(浏览器)的状态和标识(很少用到);
  5. screen:屏幕窗口信息(很少用到);

二、window对象

1、window对象在浏览器中可以从两个视角来看待

1.1、视角一:全局对象。

我们知道ECMAScript其实是有一个全局对象的,这个全局对象在Node中是global, 在浏览器中就是window对象;

1.2、视角二:浏览器窗口对象。

作为浏览器窗口时,提供了对浏览器操作的相关的API;

重点了解一下

事实上对于浏览器和Node中全局对象名称不一样的情况目前已经指定了对应的标准,称之为globalThis,并且大多数现代浏览器都支持它;

windwos === globalThis

global === globalThis

  1. 放在window对象上的所有属性都可以被访问;
  2. 使用var定义的变量会被添加到window对象中;
  3. window默认给我们提供了全局的函数和类:setTimeout、Math、Date、Object等;

2、window对象的作用

事实上 window 对象上肩负的重担是非常大的:

  1. 第一:包含大量的属性,localStorage、console、location、history、screenX、scrollX 等等(大概60+个属性);
  2. 第二:包含大量的方法,alert、close、scrollTo、open等等(大概40+个方法);
  3. 第三:包含大量的事件,focus、blur、load、hashchange等等(大概30+个事件);
  4. 第四:包含从EventTarget继承过来的方法,addEventListener、removeEventListener、dispatchEvent方法;
  5. MDN文档

2.1、MDN文档符号的释意

  • 删除符号:表示这个API已经废弃,不推荐继续使用了;
  • 点踩符号:表示这个API不属于W3C规范,某些浏览器有实现(所以兼容性的问题);
  • 实验符号:该API是实验性特性,以后可能会修改,并且存在兼容性问题;

3、window补充方法

  1. windows.open("./page/new.html", "_blank")

  2. windows.close()

  3. hashchange 事件(重点)

    当hash值改变的时候会触发

三、location对象

location对象用于表示window上当前链接到的URL信息

1、location的常见属性(8个)

  1. href: 当前window对应的超链接URL, 整个URL;
  2. protocol: 当前的协议;
  3. host: 主机地址;
  4. hostname: 主机地址(不带端口);
  5. port: 端口;
  6. pathname: 路径;
  7. search: 查询字符串;
  8. hash: 哈希值;

2、Location对象常见的方法(3个)

OzEkon.png

  1. assign:赋值一个新的URL,并且跳转到该URL中;
  2. replace:打开一个新的URL,并且跳转到该URL中(不同的是不会在浏览记录中留下之前的记录);
  3. reload:重新加载页面,可以传入一个Boolean类型;
  4. load:刷新下文档;

2.1、URLSearchParams

URLSearchParams 定义了一些实用的方法来处理 URL 的查询字符串。

  • 可以将一个字符串转化成 URLSearchParams 类型;
  • 也可以将一个 URLSearchParams 类型转成字符串;
2.1.1、 URLSearchParams常见的方法(4个)
  1. get:获取搜索参数的值;
  2. set:设置一个搜索参数和值;
  3. append:追加一个搜索参数和值;
  4. has:判断是否有某个搜索参数;
js
//这里添加?前面的地址 有可能获取不到第一个参数 注意
var searchStr = "?wd=中央向实际种粮农民发100亿元补贴&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1"
console.log(searchStr)
var urlFormat = new URLSearchParams(searchStr)
urlFormat.append("zhangsan", "38")
console.log(decodeURIComponent(urlFormat.toString()))
//这里添加?前面的地址 有可能获取不到第一个参数 注意
var searchStr = "?wd=中央向实际种粮农民发100亿元补贴&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1"
console.log(searchStr)
var urlFormat = new URLSearchParams(searchStr)
urlFormat.append("zhangsan", "38")
console.log(decodeURIComponent(urlFormat.toString()))

2.2、location中文编码的问题

  • 全局方法

中文会使用encodeURIComponentdecodeURIComponent进行编码和解码

四、history对象

history对象允许我们访问浏览器曾经的会话历史记录。

  1. history保存历史的方式是使用压栈的数据结构模式
  2. history改变的时候不会刷新网页,和hash属于前端路由的基础实现

1、history常见属性(2个)

  • length:会话中的记录历史的条数;
  • state:当前状态保留的一些信息

2、history常见方法(5个)

  1. back():返回上一页,等价于history.go(-1)

    返回上一层历史

  2. forward():前进下一页,等价于history.go(1)

    进入下一层历史

  3. go():加载历史中的某一页;

    根据number值 来确认返回哪一层历史记录,例:history.go(-1),history.go(1)

  4. pushState():打开一个指定的地址;

    新建一个history历史,并进行访问

    • 参数
      1. 保存的当前历史的状态信息state:可以是任意类型,通常情况下保存的是一个对象
      2. 没用 暂时没有几个浏览器支持,可以查阅下mdn文档
      3. 你将要访问的path路径

    history.pushState({name: "zhangsan" , age: "17"}, "" ,"push")

  5. replaceState():打开一个新的地址,并且使用replace

    替换当前层级的历史记录和状态

    history.replaceState({action: "replaceState"}, "", "forward")

五、navigator对象(很少使用)

  • navigator 对象表示用户代理的状态和标识等信息。
  • javaScript高级程序设计中的图

OzVYAs.png

六、screen对象(很少使用)

  • screen主要记录的是浏览器窗口外面的客户端显示器的信息:

    比如屏幕的逻辑像素 screen.width、screen.height;

  • 截图来自javaScript高级程序设计

OzVG7j.png

七、JSON

在目前的开发中,JSON是一种非常重要的数据格式,它并不是编程语言,而是一种可以在服务器和客户端之间传输的数据格式。

JSON的全称是JavaScript Object Notation(JavaScript对象符号)

  • JSON是由Douglas Crockford构想和设计的一种轻量级资料交换格式,算是JavaScript的一个子集;
  • 但是虽然JSON被提出来的时候是主要应用JavaScript中,但是目前已经独立于编程语言,可以在各个编程语言中使用;
  • 很多编程语言都实现了将JSON转成对应模型的方式;

1. 介绍其他的传输格式

  1. XML:在早期的网络传输中主要是使用XML来进行数据交换的,但是这种格式在解析、传输等各方面都弱于JSON,所以目前已经很少在被使用了;

    还久之前的技术了 webService 的时候在使用,配置文件现在也是很少用了

  2. Protobuf:另外一个在网络传输中目前已经越来越多使用的传输格式是protobuf,但是直到2021年的3.x版本才支持JavaScript,所以目前在前端使用的较少;

    未来有可能取代JSON

2. json的使用场景

  1. Json 易于机器的解析和生成。
  2. 网络数据的传输;存放token 异步访问数据
  3. 项目的某些配置文件;
  4. 非关系型数据库(NoSQL)将json作为存储格式;

3. JSON基本语法

  • JSON的顶层支持三种类型的值
    1. 简单值:数字(Number)、字符串(String,不支持单引号)、布尔类型(Boolean)、null类型;
    2. 对象值:由key、value组成,key是字符串类型,并且必须添加双引号,值可以是简单值、对象值、数组值;
    3. 数组值:数组的值可以是简单值、对象值、数组值

4. JSON序列化

如果我们直接存放一个对象,这个对象会被转化成 [object Object] 格式的字符串, 并不方便查看,这个时候就需要序列化

4.1、什么是序列化(百度百科)

  1. 序列化. 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。

  2. 在序列化期间,对象将其当前状态写入到临时或持久性存储区。

  3. 以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

​ 序列化使其他代码可以查看或修改,那些不序列化便无法访问的对象实例数据。. 确切地说,代码执行序列化需要特殊的权限:即指定了 SerializationFormatter 标志的 SecurityPermission。. 在默认策略下,通过 Internet 下载的代码或 Internet 代码不会授予该权限;只有本地计算机上的代码才被授予该权限。.

4.2、JSON序列化方法

在ES5中引用了JSON全局对象,该对象有两个常用的方法:

  1. stringify方法:将JavaScript类型转成对应的JSON字符串;
  2. parse方法:解析JSON字符串,转回对应的JavaScript类型;
4.2.1. stringIfy方法

参数space:如果对象本身包含toJSON方法,那么会直接使用toJSON方法的结果

js
//注意这里的key值,如果books不是对象的话key为空
//第三个参数,是用来格式化文档的
var data = JSON.stringify(books, function (key, value) {
  // console.log(key, value)
  return value
}, 4)
console.log(data)
//注意这里的key值,如果books不是对象的话key为空
//第三个参数,是用来格式化文档的
var data = JSON.stringify(books, function (key, value) {
  // console.log(key, value)
  return value
}, 4)
console.log(data)
4.2.2. parse方法

JSON.parse() 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象。

js
var dataStr = JSON.parse(data, function(key, value) {
  if(value.id === 3) {
    value.price = 1999999
  }
return value
})
var dataStr = JSON.parse(data, function(key, value) {
  if(value.id === 3) {
    value.price = 1999999
  }
return value
})
4.2.3. JSON的方法注意事项
  1. json 可以实现深拷贝
  2. json 在stringtiy undefined 和 null 的时候正常但是 parse 的时候会报错
  3. 深拷贝也有缺点
    1. 遇见函数的时候会忽略
    2. 拷贝循环引用的时候会报错, 就像 windows 对象中包括 windows
    3. 不能拷贝 Symbol

八、localStorage和sessionStorage

SessionStorage译为“会话存储”,也是HTML5新增的一个存储对象, 用于本地临时存储同一窗口的数据,在关闭窗口之后将会删除这些数据,SessionStorage浏览器一般支持5M,通常以键/值对形式的字符串进行存储。

LocalStorage生命周期是永久,除非主动清除LocalStorage信息,否则这些信息将一直存放在客户端。而SessionStorage生命周期是临时,仅在当前会话窗口有效,关闭页面或浏览器数据就会自动被清除。

第四章,知识补充

  1. 在html页面可以直接获取元素

    html
    <input id="inp" type="text" >
    	<!-- 这样也会直接调用事件 -->
    	<div id="box" class="box" onclick="inp.focus()"> </div>
    
        <script>
         
         //可以直接拿到 box 元素,js变量会放到windows
         console.log("box", box)
    
        </script>
    <input id="inp" type="text" >
    	<!-- 这样也会直接调用事件 -->
    	<div id="box" class="box" onclick="inp.focus()"> </div>
    
        <script>
         
         //可以直接拿到 box 元素,js变量会放到windows
         console.log("box", box)
    
        </script>