# Window对象

# BOM

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

  • window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的

  • window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)

    • navigator对象:包含有关浏览器的信息,如名称,版本和系统等
    • location对象:包含当前网页文档的URL信息
    • document对象:HTML 文档
    • history对象:包含浏览器窗口访问过的URL信息
  • document 是实现 DOM 的基础,它其实是依附于 window 的属性。

  • 注:依附于 window 对象的所有属性和方法,使用时可以省略 window

# 定时器-延时函数

  • JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout

  • 语法:

    setTimeout(回调函数, 等待的毫秒数)
    
  • setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window

  • 清除延时函数:

    let timer = setTimeout(回调函数, 等待的毫秒数)
    clearTimeout(timer)
    
  • 结合递归函数可以使用setTimeout 实现 setInterval 一样的功能

    • 递归函数:自己调用自己就是递归函数
    • 递归函数容易造成死递归,一定要加退出条件
<div class="clock"></div>
<script>
	let clock = document.querySelector('.clock')
	function myInterval(){
		let d = new Date();
		clock.innerText = d.toLocaleString();
		//延时任务,自调用
		setTimeout(myInterval, 1000)
	}
	//启动定时任务
	myInterval();
</script>
  • 两种定时器对比:

    • setInterval 的特征是重复执行,首次执行会延时

    • setTimeout 的特征是延时执行,只执行 1 次

    • setTimeout 结合递归函数,能模拟 setInterval 重复执行

    • clearTimeout 清除由 setTimeout 创建的定时任务

# JS 执行机制

# JS 是单线程

  • JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。

  • 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

# 同步和异步

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出Web Worker 标准,允许JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。

  • 同步

    • 前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步
    • 做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
  • 异步

    • 你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

    • 他们的本质区别: 这条流水线上各个流程的执行顺序不同。

# 同步任务和异步任务

  • 同步任务

    • 同步任务都在主线程上执行,形成一个执行栈。
  • 异步任务

    • JS 的异步是通过回调函数实现的。

    • 一般而言,异步任务有以下三种类型::

      • 普通事件,如 click、resize 等
      • 资源加载,如 load、error 等
      • 定时器,包括 setInterval、setTimeout 等
    • 异步任务相关添加到任务队列中(任务队列也称为消息队列)。

# JS 执行机制

(1)先执行执行栈中的同步任务。

(2)异步任务放入任务队列中。

(3)一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)。

  • 大白话: 在任务执行时,我们会把所有的任务分为两类:一类叫同步任务,同步任务在主线程上执行,形成一个执行栈,执行栈里的任务先执行。另一类叫异步任务,异步任务是通过回调函数实现的,一般有三种类型:普通事件、资源加载、定时器等。异步任务会被添加到任务队列中。当执行栈里的任务全部执行完毕后,系统会按异步任务中的执行顺序读取任务队列中的异步任务,被读取的异步任务会结束等待状态而进入到执行栈,然后开始执行。

# location对象

  • location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分

  • 常用属性和方法:

    • href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转

      //可以得到当前文件URL地址
      console.log(location.href)
      //可以通过js方式跳转到目标地址
      location.href = 'http://www.baidu.com'
      
    • search 属性获取地址中携带的参数,符号 ?后面部分

      console.log(location.search)
      
    • hash 属性获取地址中的哈希值,符号 # 后面部分

      console.log(location.hash)
      
      • 后期vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如 网易云音乐
    • reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新

      <button>点击刷新<button>
      <script>
      	let btn = document.querySelector('button')
      	btn.addEventListener('click', function(){
      		//强制刷新,类似于ctrl+f5
      		location.reload(true)
      	})
      </script>
      
  • navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息

  • 常用属性和方法:

  • 通过 userAgent 检测浏览器的版本及平台

    // 检测 userAgent(浏览器信息)
    !(function () {
    	const userAgent = navigator.userAgent
    	// 验证是否为Android或iPhone
    	const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
    	const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
    	// 如果是Android或iPhone,则跳转至移动站点
    	if (android || iphone) {
    		location.href = 'http://m.itcast.cn'
    	}
    })()
    

# histroy对象

  • history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等

  • 常用的属性和方法:

    history对象方法 作用
    back() 可以后退功能
    forward() 前进功能
    go(参数) 前进后退功能 参数如果是1前进1个页面,如果是-1后退1个页面
  • 例如:

    qianjin.addEventListener('click', function(){
    	history.forward()
    	//history.go(1)
    })
    
    houtui.addEventListener('click', function(){
    	history.back()
    	//history.go(-1)
    })
    
  • history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到。

# 本地存储

# 本地存储特性

  • 随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
    • 数据存储在用户浏览器中
    • 设置、读取方便、甚至页面刷新不丢失数据
    • 容量较大,sessionStorage和localStorage约 5M 左右

# localStorage

  • 生命周期永久生效,除非手动删除 否则关闭页面也会存在

  • 可以多窗口(页面)共享(同一浏览器可以共享)

  • 以键值对的形式存储使用

    //存储数据:
    localStorage.setItem(key, value)
    
    //获取数据:
    localStorage.getItem(key)
    
    //删除数据:
    localStorage.removeItem(key)
    
    • 注意:字符串要放在''内
  • 本地查看,以谷歌浏览器为例:右键单击-检查-Application-Local Storage

  • 存储复杂数据类型存储

    • 本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,再存储到本地

    • JSON.stringify(复杂数据类型)

      • 将复杂数据转换成JSON字符串 存储 本地存储中
      let obj = {
      		uname: '小苏同学',
      		age: 18,
      		address: '沈阳师范大学'
      	}
      	localStorage.setItem('obj', JSON.stringify(obj))
      
    • JSON.parse(JSON字符串)

      • 将JSON字符串转换成对象 取出 时候使用
      console.log(JSON.parse(localStorage.getItem('obj')))
      

# sessionStorage(了解)

  • 生命周期为关闭浏览器窗口

  • 在同一个窗口(页面)下数据可以共享

  • 以键值对的形式存储使用

  • 用法跟localStorage 基本相同

# 自定义属性

  • 固有属性:

    • 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作
  • 自定义属性:

    • 由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API

    • element.setAttribute('属性名', '属性值') // 设置自定义属性

      <div id='mydiv' class='nav'></div>
      
      
      <!--创建属性时,对于标签中已存在的属性,则会进行赋值操作,注意class比较特殊,它对应的class而不是className-->
      let div = document.querySelector('#mydiv')
      console.log(div.setAttribute('class','footer'));   //<div id='mydiv' class='footer'>
      
    • element.getAttribute('属性名') // 获取自定义属性

      <div id='mydiv'></div>
      
      let div = document.querySelector('#mydiv')
      console.log(div.getAttribute('id'));   //mydiv
      
    • element.removeAttribute('属性名') // 删除自定义属性

      <div id='mydiv' index='1'></div>
      
      let div = document.querySelector('#mydiv')
      console.log(div.removeAttribute('index'));
      
  • 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。

  • 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性,H5因此给我们新增了自定义属性

    • H5规定自定义属性 data- 开头作为属性名并且赋值

    • data-自定义属性:

      • 传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在标签上一律以data-开头

      • 在DOM对象上一律以dataset对象方式获取

<div class="box" data-id="10"></div>
<script>
	let box = document.querySelector('.box')
	console.log(box.dataset.id)  //10
</script>
  • 可以通过 element.dataset.自定义属性名 或者 element.dataset['自定义属性名']获取自定义属性(有严重的兼容性问题 ie11才开始支持),并且只支持 data-开头的

    • dataset是一个集合,里面存放了所有以data开头的自定义属性
    <div id='mydiv' data-index='1'></div>
    例如:获取index属性的值
    
    let div = document.querySelector('#mydiv')
    div.dataset.index
    div.dataset['index']
    
    • 如果自定义属性中有多个 - 连接的单词,我们获取的时候采取驼峰命名法

      <div id='mydiv' data-list-name='su'></div>
      
      let div = document.querySelector('#mydiv')
      div.dataset.listName
      div.dataset['listName']
      

# 正则表达式

# 概念

  • 正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象

  • 通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。

  • 正则表达式在 JavaScript中的使用场景:

    • 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)

      • 比如用户名: /^[a-z0-9_-]{3,16}$/
    • 过滤掉页面内容中的一些敏感词(替换)

    • 从字符串中获取我们想要的特定部分(提取)等 。

# 语法

(1)定义规则 (2)查找

  • JavaScript 中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:

    • 定义正则表达式语法:

      let 变量名 = /表达式/
      
      • 其中 / / 是正则表达式字面量
      • 比如:
      let reg = /前端/
      
    • 判断是否有符合规则的字符串:

      • test() 方法 用来查看正则表达式与指定的字符串是否匹配

        • 语法:

          regObj.test(被检测的字符串)
          
        • 比如:

          let str = '前端开发, web前端, 软件开发, 软件测试'
          let reg = /前端/
          let re = reg.test(str)
          console.log(re)  //true
          
          • 如果正则表达式与指定的字符串匹配 ,返回true,否则false
    • 检索(查找)符合规则的字符串:

      • exec() 方法 在一个指定字符串中执行一个搜索匹配

        • 语法:

          regObj.exec(被检测的字符串)
          
        • 比如:

          let str = '前端开发, web前端, 软件开发, 软件测试'
          let reg = /前端/
          let re = reg.exec(str)
          console.log(re)  //返回的是个数组
          
          • 如果匹配成功,exec() 方法返回一个数组,否则返回null
  • 正则表达式检测查找 test方法和exec方法有什么区别?

    • test方法 用于判断是否有符合规则的字符串,返回的是布尔值 找到返回true,否则false
    • exec方法用于检索(查找)符合规则的字符串,找到返回数组,否则为null

# 元字符

  • 普通字符:

    • 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。
    • 也就是说普通字符只能够匹配字符串中与它们相同的字符。
  • 元字符(特殊字符)

    • 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
      • 比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm…..
      • 但是换成元字符写法: [a-z]
  • 参考文档:

    • MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
    • 正则测试工具: http://tool.oschina.net/regex
  • 为了方便记忆和学习,我们对众多的元字符进行了分类:

    • 边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)
    • 量词 (表示重复次数)
    • 字符类 (比如 \d 表示 0~9)

(1)边界符

  • 正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

    边界符 说明
    ^ 表示匹配行首的文本(以谁开始)
    $ 表示匹配行尾的文本(以谁结束)
    • 如果 ^ 和 $ 在一起,表示必须是精确匹配。 例如:^哈$ 匹配只能是 哈

(2)量词

  • 量词用来 设定某个模式出现的次数

    量词 说明
    * 重复零次或更多次
    + 重复一次或更多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次
    • 例如:

      /a*/   			//代表a可以出现0次或更多次,a出现的次数n>=0
      /a+/   			//代表a至少出现1次或更多次,a出现的次数n>=1
      /a?/   			//代表a可以出现0次或1次,a出现的次数0||1
      /a{3}/ 			//代表a至少连续出现3次,可以多次,不能少于3。如baaad、caaaav
      /^a{3}$/ 		//代表只能是aaa,开头结尾都是a,且连续出现3次
      /^a{3}/			//代表a开头,且连续出现最少3次。如aaaa、aaab
      /a{3}$/			//代表a结尾,且连续出现最少3次。如aaaa、baaa
      /a{3,}/			//代表a至少连续出现3次或更多次。如scdaaaw、sdcaaaasd
      /a{3,6}/		//代表a至少连续出现3次或更多次
      /^a{3,6}$/	//代表a至少连续出现3~6次
      
      • 注意: 逗号左右两侧千万不要出现空格
  • [ ] 匹配字符集合

    • 例如:[abc].test('abc')
      • 后面的字符串只要包含 abc 中任意一个字符,都返回 true。
      • []理解为只能存储1个字符,[abc]可以理解为abc中的任意一个字符,三选一,可以是a,可以是b,可以是c
  • [ ] 里面加上 - 连字符

    • 使用连字符 - 表示一个范围

      console.log(/^[a-z]$/.test('c')  //true
      
    • 比如:

      • [a-z] 表示 a 到 z 26个英文字母都可以
      • [a-zA-Z] 表示大小写都可以
      • [0-9] 表示 0~9 的数字都可以
    • 认识下:

      //腾讯QQ号:	 
      ^[1-9][0-9]{4,}$      //腾讯QQ号从10000开始
      
      //中文验证:	  
      ^[\u4e00-\u9fa5]{2,8}$/
      
      //日期格式:
      ^\d{4}-\d{1,2}-\d{1,2}
      
  • [ ] 里面加上 ^ 取反符号

    • 比如:
      • [^a-z] 匹配除了小写字母以外的字符
      • 注意要写到中括号里面
  • . 匹配除换行符之外的任何单个字符

  • 预定义:指的是某些常见模式的简写方式。

    预定类 说明
    \d 匹配0-9之间的任一数字,相当于[0-9]
    \D 匹配所有0-9以外的字符,相当于[^0-9]
    \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
    \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
    \s 匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]
    \S 匹配非空格的字符,相当于[^\t\r\n\v\f]

# 修饰符

  • 修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等

  • 语法:

    /表达式/修饰符
    
    • i 是单词 ignore 的缩写,正则匹配时字母不区分大小写

      • 例如:

        console.log(/a/i.test('a'))	//true
        console.log(/a/i.test('A'))	//true
        
    • g 是单词 global 的缩写,匹配所有满足正则表达式的结果

  • 替换 replace 替换

  • 语法:

    字符串.replace(/正则表达式/, '替换的文本')
    
    • 例如:

      let str='小苏同学爱吃苹果'
      console.log(str.replace(/苹果/,'香蕉'))		//小苏同学爱吃香蕉
      
  • 扩展

    for(){
    	break  //退出循环  结束循环
    	continue  //结束本次循环,继续下一次循环
    }
    
    function fn(){
    	return  //有值便返回值,没有值便结束函数
    }