函数
函数中,如果实参的个数和形参的一样,则输出正常。
函数中,如果实参的个数大于形参的个数,则会取到形参的个数的长度;
函数中,如果实参的个数小于形参的个数,则多的形参会定义为underfined;
函数的返回值:
function(){ return 需要返回的结果 }
1、函数只是实现某种功能,最终的结果需要返回给函数的调用者;
2、只要函数遇到return,就把后边的结果,返回给函数的调用者;
function getResult(){ return 666 } getResult() //等于是 getResult() = 666
function getMax(num1,num2){ if(num1> num2){ return num1; }else { return num2; } } getMax(1,6) //最终结果是返回的是6
利用函数算数组中的最大值:
function getArr(arr){ let max = arr[0] for(let i =1;i<arr.length;i++){ if(arr[i] > max){ max = arr[i] } } return max } let max = getArr([1,2,3,5,6]) //最终结果是6
return 只能返回一个值,并且return后边的语句不执行。
如果不return返回值,则调用时的值就是underfined
arguments的使用
function arr(){ console.log(arguments); //会以假数组方式显示, } arr([1,2,3])
1、具有数组的length属性,
2、按照索引的方式进行存储
3、它没有真正数组的一些方法
(它是一个函数内置的)
函数有两种声明方式:
1、第一种是命名函数:
function fn(){}
fn()
2、匿名函数
var fun = function(){}
调用方式是fun()
注:此时的fun()是变量
作用域:
分为两种:一种是全局作用域,另一种是局部作用域。
1、全局作用域就是整个script标签,或者一个单独的js文件。
2、局部作用域(函数作用域),在函数内部就是局部作用域,
作用域链:内部函数访问外部函数的变量,采取的就是查找的方式来决定取哪个值,这样的结构称为“作用域链”,就近原则。
let Num = 10; function fn(){ let Num = 20; function fun() { console.log(Num); } }
打印输出结果为:20,就近原则
JS引擎运行js分为两部:
1
(1)、预解析:js引擎会把js里边的var 还有 function提升到当前作用域的最前边;
(2)、顺序执行,按照书写顺序从上往下执行;
2、
预解析分为:变量预解析(变量提升)和函数预解析(函数提升)
(1)、变量提升就是把所有的变量声明提升到当前作用域最前边,赋值的不提升;
(2)、函数提升就是把所有的函数声明提升到当前作用域的最前边,不调用函数
对象
对象就是一个具体的事物;在js中对象就是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串,数值,数组等;
对象是由属性和方法组成
属性:就是事物的特征,在对象中用属性来表示;
方法:事物的行为,在对象中用方法来表示;
创建对象的三种方法:
一、利用字面量创建对象
let obj = { uname: 'abc', age: 20, sayHi: function(){} }
里边的属性采取键值对形式;
多个属性和方法之间用逗号隔开;
方法后边跟着是一个匿名函数;
1、使用对象属性:
对象.属性
2、使用对象方法:
对象.方法
二、变量、属性、方法、函数的区别
变量和属性:都是用来存放数据的
区别:
变量:单独声明并赋值,使用时候直接写变量名,单独存在;
属性:不需要单独声明,但是使用时必须是对象.属性
函数和方法:都是用来实现某种功能,做某件事
区别:
函数是单独声明的,并且调用时,函数名()
方法是在对象里边,使用时,对象.方法()
二、利用new object()创建对象
let obj = new Object(); obj.uname = 'aaa' obj.age = 10 obj.sayHi = function(){}
调用时:
obj.sayHi(); obj.uname;
利用构造函数创建对象:
构造函数:
function 构造函数名(){ this.属性 = 值 this.方法 = function(){} } new 构造函数名()
function Star(uname, age, sex){ this.name = uname this.age = age this.sex = sex } let a = new Star('姓名',30,'男')
1、构造函数名首字母大写;
2、构造函数不需要return,就可以返回结果
3、调用构造函数必须要有new
构造函数和对象的区别:
构造函数:泛指一大类;
对象:是一个具体的事物;
构造函数创建对象的执行过程为:
1、new 构造函数可以在内存中创建一个空对象,
2、this 指向这个空对象;
3、执行构造函数里边的代码,添加属性和方法
4、返回这个新对象,所以不需要在再外边return 了
如何遍历一个对象:
使用for......in
for(变量 in 对象){}
for(let i in obj){ console.log(i); }
这样写时,遍历出来的是变量名
------------------------------------------------------------------
for(let j in obj){ console.log(obj[j]); }
当这样写时,输出的结果是属性值;
数组对象
数组去重
目标:把旧数组的里边不重复的元素选取出来,放到新的数组中,重复的去掉;
核心算法:遍历旧的数组,然后每遍历出来一个就拿这个去和新数组中的每一个进行查询,如果存在就不添加,反之添加;
(如果返回的是-1,表示没有)
function arr(arr) { var newArr = [] for(let i =0;i<arr.length;i++){ if(newArr.indexOf(arr[i]) === -1){ newArr.push(arr[i]); } } return newArr } let ab = arr([11,2,11,3,5,6])
返回结果就是[11,2,3,5,6]
数组转字符串
字符串对象
var str = ‘andy’console.log(str.length) 会打印输出4
这样的过程就是基本包装类型:把简单的数据类型,包装成为复杂数据类型
相当于这样:
let temp = new String ('andy') 1、构造函数,把简单数据类型包装为复杂数据类型
str = temp 2、把临时变量值赋值给str
temp = null; 3、销毁这个临时变量
基本包装类型类型:
一共有三种,分别是:String Number Boolean,把简单数据类型包装为复杂数据类型就可以拥有属性和方法。
字符串对象——字符串的不可变性
当改变字符串的变量时,实际上是又开辟了一个空间。
let ab = 'zifuchuan' ab = 'zhi'
实际上是开辟了两个空间
字符串对象的——根据字符返回位置1、indexOf('要查找的字符', 开始的位置): 返回指定内容在元字符串中的位置,如果找不到就是-1,找到就返回索引号。
2、lastIndexOf(): 从后往前找,只找第一个匹配的。
let str = 'obasdffbobaobadobaob' let index = str.indexOf('o'); let num = 0 while(index !== -1){ num ++; index = str.indexOf('o', index + 1) }
字符串对象——根据位置返回字符
charAt:返回指定位置的字符(Index字符串的索引号)
let str = 'asdf' for(let i =0;i<str.length;i++){ console.log(charAt(i)); }
charCodeAt(index) :获取指定位置字符的ASCII 码,
例如:str.charCodeAt(0); 也就是 a ,a的ASCII码为97
str[index] 获取指定位置字符,str[0] ,a
案例:
let str = 'asdfsadf' let obj = {} for(let i = 0;i< str.length; i++){ let chars = str.charAt(i); //根据位置返回字符 if(obj[chars]){ //判断对象里是否已经存在这个属性 obj[chars]++; //如果已经存在就把它加1 } else { obj[chars] = 1; //如果对象里边没有这个属性就赋值为1; } }
现在对象obj里边存的是每个字符出现的次数,现在要算出最大值:
遍历对象for ......in
let maxNum = 0 let ch = '' for (let a in obj){ if(obj[a] > maxNum) { maxNum = obj[a] ch = a } } console.log(maxNum); 得到出现最多的次数 console.log(ch); 得到出现最多的属性名
字符串操作方法
concat(str1, str2) : concat()方法用于连接两个或者多个字符串。拼接字符串,等效于+
substr(start, length) : 从start 位置开始(索引号),length 取的个数。
slice(Starr,end) : 从start位置开始,一直截取到 end 位置,包括end 。
substring(start, end ) : 从 start 位置开始,截取到 end 位置,但是不包括end
replace('被替换的', ' 替换为的字符') ,
split( '分隔符' ) : 把字符串,从指定的分隔符分隔为几个数组,(join()把数组转换为字符串)
简单数据类型和复杂数据类型关系
1、简单数据类型
(1)、简单数据类型里边有一个特殊的null,它返回的是一个空对象object
堆和栈:
1、栈:
简单数据类型存放到栈里边,在里边直接开辟一个空间存放值;
2、堆:
复杂数据类型存放在堆中,首先在栈中存放地址,用十六进制表示,然后这个地址指向堆中的数值;所以当改变堆中的数据是,由于指向的是同一个地址,所以值会发生改变;
获取特殊元素(body,html)
1、获取到body元素
document.body
2、获取到html元素,
document.documentElement
事件三要素:
分别是: 事件源,事件类型,处理程序
事件源:要触发的对象;
事件类型:单击,移动等;
处理程序:点击事件触发的逻辑;
事件基础:
innerHTML和innerText的区别:
1、innerText不识别html标签,并且去除换行和空格
2、innerHTML识别html标签
这两个属性是可读写的,可以获取元素里边的内容
操作元素——表单
<button></button> <input type = 'text' value = "请输入内容"> <script> let btn = document.querySelector('button'); let ipt = document.querySelector('input'); btn.onclick=function(){ ipt.value = '修改了表变里边的input的值'; } </script>
注:在元素的事件中,this指向的是函数的调用者
let btn = document.querySelector('button'); let ipt = document.querySelector('input'); btn.onclick=function(){ ipt.value = 'input的值发生变化' this.disabled = true //此时this就是相当于btn这个按钮 }
在上边的实例中,this就是指向的btn。
操作元素——属性,样式
可以通过js修改元素的大小,颜色,位置等样式。
1、element.style 行内样式操作
let div = document.querySelector(div); div.onclick = function(){ this.style.backgroundColor = 'pink' this.style.width = '300px' }
里边的样式采取驼峰命名法,并且由于是使用的style行内样式权重较高。
2、element.className 类名样式操作:
.change{ font-size: 25px color: white; margin-top: 10px } <div>使用element.className</div> <script> let dv = document.querySelector('div'); dv.onclick = function(){ dv.className = 'change' } </script>
注:如果样式较少或者功能简单,可以采用行内样式方式修改元素;
如果样式较多,情况下可以使用类名的方式;由于class是一个保留字,所以类名是用的className 来操作;
className会直接更改元素的类名,会覆盖原来的类名;
如果想不替换原来的类名可以在添加类样式时,把原来的类名放在前边,空格后边加上新添加的类名。
操作元素总结:
操作元素内容:innerHTML
操作常见元素属性: src href title等
操作表单元素属性: type value disabled等
操作元素样式属性: element.style className
排他思想:
<button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> let btns = document.getElementsByTagName('button'); for(let i = 0;i<btns.length;i++){ btn[i].onclick = function(){ for(let j = 0;j<btns.length;j++){ btns[j].style.backgroundColor = ''; } btn[i].style.backgroundColor = 'pink' } } </script>
表格隔行变色:
.bg{ background-color: pink } <body> <table> <thead></thead> <tbody></tbody> </talbe> <script> //获取到所有的在tbody里边的行,tr let trs = document.querySelector('tbody').querySelectorAll('tr'); //利用循环注册绑定事件 for(let i = 0;i<trs.length;i++){ trs[i].onmouseover= function(){ this.className = 'bg' } trs[i].momouseout= function(){ this.className = '' } } </script> </body>
案例重点:全选,单选
首先:全选和取消全选的:
let chaAll = document.getElementById('chaAll'); let chas = document.getElementById('chas'); chaAll.onclick=function(){ console.log(this.checked); checked可以得到当前复选框的选中状态,选中就是true,反之false for(let i = 0;i<chas.length;i++){ chas[i].checked = this.checked ; // 把当前全选状态赋值给下边遍历的字选项, } }
然后:下边子选项判断是否全部选中,给所有子选项绑定点击事件,每次点击都循环查看是否有选中的,如果有一个没有选中,则全选就不勾选;
let chaAll = document.getElementById('chaAll'); let chas = document.getElementById('chas'); chaAll.onclick=function(){ console.log(this.checked); checked可以得到当前复选框的选中状态,选中就是true,反之false for(let i = 0;i<chas.length;i++){ chas[i].checked = this.checked ; // 把当前全选状态赋值给下边遍历的字选项, } } for(let j = 0;j<chas.length;j++){ chas[j].onclick=function(){ let flag = true for(let i =0;i<chas.length;i++){ if(!chas[i].checked){ flag = false break; } } chall.checked = falg } }
获取到元素:
可以通过document.querySelector,等方法获取到元素,并且可以通过使用
dir,打印输出元素的属性,方法,console.dir()
可以通过使用document.getElementByTagName('li')获取到元素,返回的是一个伪数组的对象集合(如果没有元素,返回的是一个空的伪数组)
如果需要获取到某个元素里边的元素,可以通过这样方式使用:
元素.getElementByTagName(),由于返回的是伪数组,所以需要指定索引号,指定元素;
获取元素的属性值:
有两种方式:1、可以通过element.属性 ,可以获取内置属性,自身自带属性;
2、element.getAttribute('属性'),获取的自定义属性;
设置元素属性值:
(1)element.属性 = '值'
(2)element.setAttribute('属性', 值): element.setAttribute('index', 2):
移除元素的属性值:
removeAttribute('属性'): div.removeAttribute('index');
tab栏案例:
分析:1、tab栏切换有两个大模块
2、上边的选项卡,点击哪个,哪个样式就发生变化
3、下边的模块内容,会跟随上边的选项卡变化,所以下面的模块变化写到点击事件里边;
4、规律:下面的模块显示内容和上面的选项卡一一对应,相匹配。
5、核心思路:给上面的栏,每个添加一个自定义属性'inde',属性值从零开始
6、当我们点击上边的哪个栏的,就获取到当前点击的自定义index属性值,其他的隐藏;
let tabList = document.querySelector('.tab_list'); let lis = document.querySelector('li'); let items = document.querySelector('.item'); for循环绑定点击事件 for(let i = 0;i<tabList.length;i++){ lis[i].setAttribute('index', i); lis[i].onclick=function(){ for(let j=0;j<lis.length;j++){ //排它思想,清空其他的背景 lis[j].className = '' } lis[i].className = 'current' //给点击的设置背景 2。下边显示内容模块 let index = this.getAttribute('index'); //获取到当前点击的index属性值 for(let i =0;i<item.length;i++){ item[i].style.display = 'null' } item[index].style.display = 'block' } }
H5自定义属性
自定义属性的目的:为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中。
自定义属性是通过:getAttribute('属性')获取
但是有些自定义属性容易引起歧义,不容易判断是元素内置属性还是自定义属性。所以H5新添加了自定义属性。
H5规定,自定义属性要以 'data-' 作为开头并且赋值。
如:<div data-index = '1' > </div>
H5新增的获取自定义属性的方法:element.dataset.index 获取 element.dataset['index']
<div getTime="20" data-index = '2' data-list-name = 'andy'></div> <script> let div = document.querySelector('div'); console.log(div.getAttribute('getTime')); div.setAttribute('data-time', 20) h5新增的获取自定义属性的方法,它只能后去data-开头的 dataset是一个集合里存放了所有以data开头的自定义属性 console.log(div.dataset); 如果自定义属性里边有多个 ‘-’ 链接的单词,我们获取的时候采取驼峰命名法。 </script>
节点操作:
获取节点通常两种方式:
1、利用DOM 提供的方法获取元素,
例如:document.querySelector,
document.getElementById
document.getElementByTagName()
2、利用节点层级关系获取元素;
利用父子,兄弟节点获取元素
node.parentNode(获取到的是当前元素最近的父级元素)
节点概述:
一般节点至少拥有三个基本属性:nodeType节点类型;nodeName节点名称;nodeValue节点值
元素节点 nodeType为1
属性节点 nodeType 为 2
文本节点 nodeType 为 3 (空格,换行,文字等)
父节点操作parentNode:
<body> <ul> 父元素 <li>子元素</li> </ul> <script> let lis = document.querySelector('子节点'); console.log(lis.parentNode); 打印输出当前的lis的父节点; </script> </body>
注:就近原则。(只能获取到最近的父级节点)
子节点操作parentNode.childNodes
但是,此方式会获取到所有的节点,元素节点,属性节点,文本节点。
<ul> <li></li> </ul> <script> let uls = document.querySelector('ul'); for(let i =0;i<uls.childNodes.length;i++){ if(uls.childNodes[i].nodeType ==1){ console.log(uls.childNodes[i]); } } </script>
所以如果获取子元素节点可以使用:parentNode.children
是一个只读属性,返回所有的子元素节点。
获取到第一个子节点:parentNode.firstChild
但是此方法会获取到是包含,元素节点,属性节点,文本节点的第一个节点;
如果只获取到第一个子元素节点:parentNode.fristElementChild,
获取到最后一个子元素几点: parentNode.lastElementChild
实例:
let nav = document.querySelector('.nav'); let lis = nav.children; //获取到下边的子元素节点 for(let i =0;i<lis.length;i++){ lis[i].children[1].onmouseover=function(){ this.children[1].style.display = 'block' } lis[i].children[1].onmouseout=function(){ this.children[1].style.display = 'none' } }
兄弟节点:
1、node.nextSibling:返回当前元素的下一个兄弟节点(包括元素节点,属性节点,文本节点),找不到则返回Null,同样包括全部的节点;
2、node.previousSibling :返回当前元素的上一个兄弟节点(包括元素节点,属性节点,文本节点),找不到则返回Null,也是返回全部的节点。
3、node.nextElementSibling: 返回当前元素的下一个元素节点,找不到返回Null;
4、node.previousElementSibling;返回当前元素的上一个元素节点,找不到返回Null
创建节点:
document.createElement('节点');
例如:document.createElement('li');
<ul></ul> let li = document.createElement('li'); 首先创建一个节点 let ul = document.querySelector('ul'); ul.appendChild(li); 创建的元素追加到当前元素里边。
如果需要向页面前边追加一个新的元素:元素.insertBefore
节点案例:简单留言发布
let btn = document.querySelector('button'); let text = document.querySelector('textarea'); let ul = document.querySelector('ul'); btn.onclick=function(){ if(text.value !==''){ let li = document.createElement('li'); li.innerHTML = text.value ul.insertBefore(li); } else{ return } }
删除节点:
node.removeChild(child) :这个方法是从DOM 中删除一个子节点,返回删除的节点
javascript:;禁止默认行为
let btn = document.querySelector('button'); let text = document.querySelector('textarea'); let ul = document.querySelector('ul'); btn.onclick=function(){ if(text.value !==''){ let li = document.createElement('li'); li.innerHTML = text.value + "<a href='javascript:;'>删除</a>" ul.insertBefore(li, ul.children[0]); 把当前li追加到ul的第一个位置 let as = document.querySelectorAll('a'); for(let i =0;i<as.length;i++){ as[i].onclick=function(){ ul.removeChild(this.parentNode); } } } else{ return } }
克隆节点(赋值节点)
node.cloneNode( true| false): 方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点
如果为true:表示为深拷贝;
如果不添加或者为false,表示为浅拷贝;
深拷贝表示节点,内容都拷贝;
浅拷贝表示只拷贝节点;
案例动态生成表格:
<body> <table cellspacing="0"> <thead> <tr> <th>name<th> <th>class<th> <th>age<th> <th>num<th> </tr> </thead> <tbody></tbody> </table> <script> let datas={ [ { name:'张三', class: '一般' age: 20 }, { name:'张三', class: '一般' age: 20 }, { name:'张三', class: '一般' age: 20 } ] } let tbody = document.querySelector('tbody'); for(let i=0;i<datas.length;i++){ let tr = document.createElement('tr'); tbody.appendChild(tr); //行里边创建单元格td,单元格的数量取决于每个对象里边的属性的个数,for...in...遍历出来对象 for(let k in datas[i]){ //创建节点td let tds = document.createElement('td'); tds.innerHTML = data[i][k] tr.appendChild(td) //把对象里边的属性值 data[i][k]赋值给td } //创建删除的单元格 let td = document.createElement('td'); td.innerHTML = "<a href='javascript:;'></a>" 向当前行里边追加删除单元格 tr.appendChild(td) } 点击删除,删除整行 let as = document.querySelectorAll('a') 获取到所有的删除的a for(let i = 0;i<as.length;i++){ //遍历所有的啊,给每个添加点击事件 as[i].onclick=function(){ tbody.removeChild(this.parentNode.parentNode) //移除节点,点击删除,它的父几点是单元格,单元格的父几点是行 } } </script> </body>
创建元素的三种方式:
1、document.write():如果页面文档流加载完毕后,在调用这段代码,会使得页面重绘;
2、document.innerHTML;
3、document.createElement();
document.innerHTML和document.createElemnet的区别:
document.innerHTML:如果采用拼接字符串的方式,效率会很低;但是如果采用先拼接到数组里,然后把这个数组用join()分隔为字符串就效率高;
document.createElement: 这样方式效率略低于innerHTML的数组方式,但是结构清晰。
DOM重点核心:
文档对象模型简称:DOM,是可扩展标记语言的编程接口;
DOM操作主要针对元素的:增删改查;
创建 :document.write
document.innerHTML
document.createElement
增加:appchild innerBefore
修改:
删除:removeChild
查询:
事件高级:
注册事件的两种方式:
传统注册事件:
1、onclick ,onmouseover等;
事件侦听注册事件:
2、addEventListener
里面的事件类型是字符串,必定加引号,而且不带on,
同一个元素,同一个事件可以添加多个侦听器
let btns = document.querySelectorAll('button'); btns[0].addEventListener('click',function(){ alert('弹出一个对话框'); }) btns[0].addEventListener('click',function(){ alert('弹出一个对话框'); })
当点击按钮时可以先后弹出两个对话框
删除事件:
传统删除事件的方式:元素.事件名 = null
let divs = document.querySelector('div') divs[0].onclick = function(){ alert(); } divs[0].onclick = null
事件侦听删除事件:
removeEventListener('事件名称', 函数)
divs[1].addEventListener('click', fun) 删除事件时候,就需要使用命名函数了 function fun(){ alert(); div[1].removeEventListener('click', fun); }
DOM事件流
DOM事件流分为三个阶段:1、捕获阶段 2、当前目标阶段 3、冒泡阶段
DOM 事件流在js代码中只能执行捕获或者冒泡其中一个阶段
onclick事件: 冒泡事件
在事件侦听中,addEventListener的第三个参数如果是true是捕获阶段,如果是false或者不写就是冒泡阶段。
什么是事件对象?
event就是一个事件对象,元素.onclick = function(event){}
例如:div.onclick = function(event){}
事件对象就是我们事件的一系列的相关数据的集合,与事件相关,比如点击事件里边包含了与点击事件有关的信息,属性,方法;鼠标移动事件包含所有的和鼠标相关的属性和方法等。
这个事件对象可以自己命名,比如e;
事件对象常见的属性和方法:
1、e.target()返回触发事件的对象,div,span
2、e.type 返回事件的类型,click ,mouseover
3、e.preventDefault() 阻止默认事件,比如不让链接跳转;
4、e.stopPropagation() 阻止事件的冒泡
e.target和this的区别:
e.target返回的是触发事件的对象(元素),
this返回的是绑定事件的对象(元素)
阻止默认行为:preventDefualt()
<a href="#"></a>
let a = document.querySelector('a');
a.addEventListener('click', function(e){
e.preventDefult(); //标准写法
})
阻止事件冒泡:stopPropagation()
事件委托:
事件冒泡本身特性,有时不需要冒泡,有时使用冒泡可以有很好的作用。
原理:
不单独给子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子阶段。
<body> <ul> <li>子节点</li> <li>子节点</li> <li>子节点</li> </ul> <script> //给父节点添加事件侦听器,利用事件冒泡给子节点添加。 let ul = document.querySelector('ul') ul.addEventListener('click',function(){ alert('点击子节点,根据点击冒泡,触发父节点事件'); }) </script> </body>
鼠标事件对象
event对象代表事件的状态,跟事件相关的一些列信息的集合。
e.clientX :返回鼠标相对于浏览器窗口可视区的X坐标;
e.clientY : 返回鼠标相对于浏览器窗口可视区的Y坐标;
e.pageX: 返回鼠标相对于文档页面的X坐标
e.pageY : 返回鼠标相对于文档页面的Y坐标
e.screenX : 返回鼠标相对于电脑屏幕的X坐标;
e.screenY: 返回鼠标相对于电脑屏幕的Y坐标;
实例:
<img src='image.png'> <script> let img = document.querySelector('img') document.addEventListener('mousemove', function(e){ let x = e.pageX let y = e.pageY img.style.left = y + 'px' img.style.top = x + 'px' }); </script>
常用的键盘事件:
1、onkeyup(事件侦听:keyup) : 键盘按键松开时触发;
2、onkeydown(事件侦听:keydown): 键盘按钮按下时触发;
3、onkeypress(事件侦听:keypress): 键盘按键被按下时触发(但是不识别特殊功能键)
键盘事件对象:
keyCode:返回的是对应键盘的ASCII码值。
keyup 和 keydown 这两个事件,不区分字母大小写,即a和A 返回keyCode的值一样
<script> document.addEventListener('keyup', function(e){ console.log(e.keyCode); }); document.addEventListener('keydown',function(e){ console.log(e.keyCode) }) </script>
但是keypress区分大小写:
A返回97
a返回65
document.addEventListener('keypress', function(e){ console.log(e.keyCode) })
案例按键按下指定键,页面有相应操作:
思路:首先判断是否按下的s键,如果按下的是s键光标定位在输入框;
然后:使用键盘事件对象的keyCode判断;
搜索框获得焦点:使用js里面的focus方法
<input type='text'> <script> let search = document.querySelector('input'); document.addEventListener('keyup',function(e){ if(e.keyCode = 83){ search.focus() } }) </script>
案例:输入框输入,显示放大数字
<body> <div> <div class = 'con'></div> <input type = 'text' placeholder="请输入内容" class = 'jd'> </div> <script> let con = document.querySelector('.con'); let int = document.querySelector('input'); int.addEventListener('keyup',function(e){ if(int.value === ''){ con.display = 'none' } else { con.display = 'block' con.innerText = int.value } }) </script> </body>
BOM部分
即浏览器对象模型;提供了独立于内容而与浏览器进行交互的对象;
BOM 把一个浏览器当做一个对象来看待;顶级对象是window;
BOM中包含DOM
BOM的构成:window对象是浏览器的顶级对象,具有双重角色;
1、它是JS访问浏览器的一个接口;
2、它是一个全局对象,定义在全局作用域中的变量,函数都会变成window的属性和方法;
所有在调用时候可以省略window;
window对象常见的事件:
一、窗口的加载事件(方法一):
window.onload = function(){}
或者:
window.addEventListener('load',function(){})
就是当文档内容(包括,图片,样式,文本,脚本文件等)完全加载完毕后会触发这个事件。
注意:
window.onload()传统注册事件只能执行一次,如果多个只会执行最后一个window.onload
window.addEventListener('load',function(){})可以有多个;
二、窗口加载事件(方法二)
window.addEventListener('DOMContentLoaded',function(){});
仅当DOM加载完毕后就可以触发,不包括样式,图片脚本等;
定时器倒计时效果:
<script> let hour = document.querySelector('.hour'); let minute = document.querySelector('.minute'); let second = document.querySelector('.second'); let inputTime = +new Date('2023-6-1 18:00:00'); //获取当指定时间的时间戳 countDown(); //为了防止定时器页面刷新空白时间,先执行一次定时器 setInterval(counTDown, 1000); //定时器每隔几秒执行一次 function countDown() { //倒计时时间戳函数 let nowTime = +new Date(); let times = (inputTime - nowTime) / 1000; 当前剩余秒数 let h = parseInt(times / 60 / 60 % 24); 获取剩余小时 let m = parseInt(times / 60 % 60) let s = parseInt(times % 60) h = h < 10 ? '0' + h : h; m = m < 10 ? '0' + h : m; s = s < 10 ? '0' + s : s; hour.innerText = h minute.innerText = m second.innerText = s } </script>
清除定时器:
<button class = 'beg'>开始定时器</button> <button class = 'stop'>关闭定时器</button> <script> let beg = document.querySelector('beg'); let stp = document.querySelector('stop'); let timers = null beg.addEventListener('click', function(){ let timers = setInterval(()=>{ console.log('123132'); },2000) }) stp.addEventListener('click', function(0){ clearInterval(timer) }) </script>
this的指向问题
1、全局作用域或者普通函数的this指向全局对象window(注意:定时器里面的this指向window)
function fun(){ console.log('this在全局作用域或者普通函数指向的是window') } window.fun()
2、在方法中this的指向,
let a = { sayHi: function(){ console.log(this) } } a.sayHi(); ------------------------- let btn = document.querySelector('button'); btn.onclick = function(){ console.log(); }
3、构造函数中this指向的是new的创建的实例
重点:
JS执行机制——同步和异步
同步:前一个任务结束后才可以执行后一个任务。程序的执行顺序和任务的顺序是一致的。通俗的就是,一次只能做一件事,只有这件事做完才可以做另一件事。
异步:可以执行好几个任务
<script> console.log('123') setTimeout(function(){ console.log('456') }) console.log('789') </script>
程序执行结果是:123789456
js执行时会先执行主线程里边的同步任务,执行完后再执行任务列队(消息队列)中的异步任务。
先执行执行栈中的同步任务,
异步任务放入任务队列中;
一旦同步任务都执行完毕,开始执行异步任务。
一般异步任务有三种类型:
1、普通事件;
2、资源加载;
3、定时器;
当多个同步异步任务都有时:
首先会先放到异步进程处理里边,事件,定时器,资源加载都会先放进这里边,对于事件,如果没有触发就不放到异步任务队列里边,定时器如果没有到事件也不会放进入。
同时,每次异步进程都会去查看任务队列里是否有任务,
location对象
window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为Location对象。
案例:获取不同页面之间的数据传递
<body> <form action = 'index.html'> 用户名:<input type = 'text' name = 'uname'> <input type = 'submit' value ='登录'> </form> </body> //从页面一向页面二跳转 <body> <div></div> <script> //location.search获取到的就是传过来url上的?后边的参数 let params = location.search.substr(1); //uname = andy let arr = params.split('='); // 利用 = 把字符串分割为两个数组 let divs = document.querySelector('div') div.innerHTML = arr[1] + '欢迎您' </script> </body>
location的常见用法:
1、location.assign():与href一样,可以跳转页面(重定向页面),带历史记录,可以后退
<body> <button></button> <script> let btn = document.querySelector('button'); btn.addEventListener('click', function(){ location.assign('http://www.baidu.com') }) </script> </body>
2、location.replace():替换当前页面,因为不记录历史,所以不能后退;
<body> <button></button> <script> let btn = document.querySelector('button'); btn.addEventListener('click', function(){ location.replace('http://www.baidu.com') }) </script> </body>
3、location.reload():重新加载页面,相当于刷新按钮或者F5,如果参数为true,强制刷新;
<body> <button></button> <script> let btn = document.querySelector('button'); btn.addEventListener('click', function(){ location.reload() //location.reload(true) 强制刷新 }) </script> </body>
navigator对象
包含浏览器的信息,有很多属性,最常用的userAgent,这个属性可以返回客户机发送服务器的user-agent头部的值。
history对象
offset相关介绍
offset简介:动态获取到当前该元素的位置(偏移),大小等。
1、获得元素距离带有定位父元素的位置。
2、获得元素自身大小(宽度高度)
3、注:返回的值不带单位。
常用的offset属性有:
①element.offsetParent:返回当前元素带有定位的父级元素,如果父级都没有定位则返回body;
(注意:它和node.parentNode有区别,前者返回带定位父元素,后者是最近一级父元素)
②element.offsetTop:返回元素相对带有定位父元素上方的偏移;
③element.offsetLeft:返回元素相对带有定位父元素左边框的偏移;
④element.offsetWidth:返回元素自身包括padding,边框,内容区的宽度,返回数值不带单位;
⑤element.offsetHeight:返回元素自身包括padding,边框,内容区的高度,返回数值不带单位;
<div style="position:relation" class = 'f'> 父元素 <div style="position:" class = 's'>子元素</div> </div> <script> let f = document.querySelector('.f'); let s = document.querySelector('s'); console.log(s.offsetParent) console.log(s.offsetTop); console.log(s.offsetLeft); console.log(s.offsetWidth); console.log(s.offseTHeight) </script>
offset和style的区别:
offset可以获取到任意样式表中的样式值;
但是获取到的值没有单位;
offsetTop和offsetLeft是包含padding和边框和内容宽度,高度的;
并且offset系列不可以修改值;
-------------------------------------
style只可以获取到行内样式表的样式值,
但是获取到的值是带有单位的;
style.width不包含有padding和border值,
style.height是可读写属性,可以获取到值,也可以赋值,所以如果需要更改样式大小值,可以使用;
<body> <div style="width: 300px"></div> <script> let d = document.querySelector('div'); d.style.width = '400px' </script> </body>
实例:获取到鼠标移动时在盒子里的坐标(e.pageX, e.pageY)
<body> <div class = 'divClass'></div> <script> let di = document.querySelector('.divClass') di.addEventListener('mousemove', function(e){ console.log(e) //打印输出的是事件对象 let x = e.pageX - di.offsetLeft let y = e.pageY - di.offsetTop console.log('当前点击盒子里坐标x 为'+x+'y坐标为:'+ y); }) </script> </body>
实例拖拽模态框案例
由于代码稍微多,具体请看pink老师教程:
【JavaScript前端课程-dom-bom-js-es6新语法-jQuery-数据可视化echarts黑马pink老师前端入门基础视频教程(500多集)持续】 https://www.bilibili.com/video/BV1Sy4y1C7ha/?p=292&share_source=copy_web&vd_source=0b14fab0cad18656d9ffed500fb3ca30关键代码如下:
<script> let login = document.querySelector('.login'); let mask = document.querySelector('.beijing'); let link = document.querySelector('#link'); let title = document.querySelector('.tit'); let closeBtn = document.querySelector('#btn'); 点击弹出让登录框,背景显示出来 link.addEventListener('click', function(){ mask.style.display = 'block' mask.style.display = 'block' }) closeBtn.addEventListener('click', function(){ mask.style.display = 'none' mask.style.display = 'none' }) title.addEventListener('mousedown', function(e){ //获取到当前鼠标按下后的下盒子里坐标 let x = e.pageX - login.offsetLeft let y = e.pageY - login.offsetTop //鼠标移动时,把当前鼠标在页面坐标减去在盒子里坐标赋值给Login document.addEventListener('mousemove', mov) function mov(e){ login.style.left = e.pageX - x login.style.top = e.pageY - y } document.addEventListener('mouseup', function(){ document.removeEventListener('mousemove', mov); }) }) </script>
元素可视区client系列
client翻译过来就是客户端,使用client系列的相关属性来获取元素可视区的相关信息。通过client的相关属性可以动态得到该元素的边框大小,和元素大小等。
client系列属性(不包括边框)
element.clientTop: 返回元素上边框的大小,没有单位
element.clientLeft: 返回元素左边框的大小,没有单位
element.clientWidth: 返回自身包括padding,内容区的宽度,没有单位
element.clientHeight: 返回自身包括padding ,内容区高度的值(没有单位)
立即执行函数:不需要调用直接执行
两种写法:
1、(function(){})()
(function(a,b){
console.log('123')
})(1,2)
括号里传参
2、(function(){}())
(function sum(a,b){
console.log('abc');
}(2,3))
元素滚动scroll系列
动态的可以获取到元素的大小,滚动距离等。
element.scrollTop:返回被卷去的上边距离,不带单位。
element.scrollLeft: 返回被卷去的左侧距离,不带单位。
element.scrollWidth: 返回元素实际自身的宽度,不包括边框,不带单位。
element.scrollHeight: 返回元素自身的高度,不包括边框,不带单位
新方法:window.pageYOffset
window.pageXOffset 分别表示:返回窗口距离X轴方向的距离,返回Y轴方向距离
<bod> <div> <span>返回头部</span> </div> <div class = 'header w'>头部</div> <div class = 'banner w'>banner</div> <div class = 'main w'>主体部分</div> <script> let sliderbar = document.querySelector('.slider-bar') document.addEventListener('scroll', function(){ console.log(window.pageYoffsetLeft); console.log(window.pageXoffsetTop); if(window.pageYoffset >= 172){ sliderbar.style.position = 'fixed' } else { sliderbar.style.position = 'absolute' } }) </script> </body>
三个系列总结:
1、首先:element.offsetWidth:获取自身的宽度高度,包括边框宽度,padding的宽度;
offset系列经常用于获取元素的位置offsetLeft和offsetTop;
2、element.scroll:获取的是被卷去部分的宽度,高度,不包括边框;scroll系列经常用于获取滚动距离,scrollLeft,scrollTop;
3、element.client:获取的是包括自身,也包括Padding,不包括边框的值,因为它可以获取边框宽度,经常用于获取滚动的距离scrollTop,scrollLeft
注:页面滚动的距离是通过window.pageXoffset或者window.pageYoffset获取到;
mouseenter和 mouseover的区别:
<body> <div class = 'f'>父盒子 <div class = 's'>子盒子</div> </div> <script> let f = document.querySelector('f'); let s = document.querySelector('s'); s.addEventListener('mouseenter', function(){ console.log('子盒子鼠标滑过不会触发父盒子') }) // ---------------------- s.addEventListener('mousemover',function(){ console.log('会冒泡到父盒子,'); }) </script> </body>
动画函数的简单封装:
注:这个简单函数需要传递两个参数。
<script> function fun(obj,num){ let timer = setInterval(function(){ if(obj.offsetLeft >= num){ clearInterval(timer) } else{ obj.offsetLeft = obj.offsetLeft + 1 + 'px' } },500) } let div = document.querySelector('div') fun(div,500) </script>
怎样给不同元素记录不同定时器
如果多个元素都使用这个定时动画函数,每次都会创建一个定时器,会影响效率。
所以可以采用为每个对象使用不同定时器(对象使用自己的定时器)
核心原理:js是一个动态语言,可以为当前对象添加属性;
同时:为了防止每次执行函数都会创建一个定时器的问题,每次执行函数之前先清除前一个定时器;
<body> <div></div> <script> function animate(obj, num){ clearInterval(obj.timer) //为了防止创建多个相同定时器,每次执行先清除前一个定时器 obj.timer = setInterval(function(){ if(obj.offsetLeft >= num){ clearInterval(tim) } else { obj.offsetLeft = obj.offsetLeft + 10 + 'px' } }, 500) } animate(div,200) </script> </body>
动画函数封装——动画缓动效果
原理:就是让元素运动速度有所变化;
思路:
1、让每次移动的距离慢慢变小,速度就相应的慢下来;
2、核心算法:(目标值 - 现在位置) / (步长数) = 每次移动的距离;
3、停止条件:让盒子位置等于目标位置就停止定时器;
<body> <div></div> <script> // obj是元素,num是目标值 function animate(obj, num){ clearInterval(obj.timer)//为了防止创建多个相同定时器,每次执行先清除前一个定时器 obj.timer = setInterval(function(){ let step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step) if(obj.offsetLeft >= num){ clearInterval(obj.timer); } obj.style.left = obj.offsetLeft + step + 'px'; }, 500) } animate(div,200) </script> </body>
动画添加回调函数:
<head> <script src='animate.js'></script> </head> <body> <div class = 'sliderbar'> <span>箭头</span> <div class = 'con'>滑动滑块</div> </div> <script> let sliderbar = document.querySelector('.sliderbar'); let con = document.querySelector('.con'); sliderbar.addEventListener('mouseenter', function(){ animate(con, -200, function(){ sliderbar.children[0].innerHTML = '滑到右边' }) }) sliderbar.addEventListener('mouseleave', function(){ animate(con, 0, function(){ sliderbar.children[0].innerHTML = '滑动回来' }) }) </script> </body>
节流阀:
防止动画执行太快,当上一个执行完毕再执行下一个;
案例:筋斗云案例
思路:
1、利用动画效果实现;
2、原始位置是0,;
3、鼠标经过某个小Li就把当前Li的OffsetLeft作为目标值;
4、鼠标离开某个小li就把目标值设为0;
5、点击那个li,就把当前li点击位置存到原始位置遍历;
<script> let current = 0; for(let i =0;i<lis.length;i++) { lis[i].addEventListener('mouseenter', function(){ animate(cloud, lis[i].offsetLeft); }) lis[i].addEventListener('mouseleave', function(){ animate(cloud, current) }) lis[i].addEventListener('click', function(){ current = this.offsetLeft; }) } </script>
移动端事件:
触屏touch事件
touchstart :手指触摸到一个DOM元素时触发;
touchmove: 手指在一个DOM元素滑动时触发;
touchend; 手指从一个DOM元素上移开时触发;
let div = document.querySelector('div'); div.addEventlistener('touchstart', function(){ console.log('移动端开始触摸事件') }) --------------------------- div.addEventlistener('touchmove', function(){ console.log('移动端在元素上移动事件'); }) ----------------------- div.addEventlistener('touchend', function(){ console.log('移开元素') })
1、触摸事件对象(TouchEvent)
有三个常见对象列表:
1.touches:正在触摸屏幕的所有手指的一个列表,有几个手指在触摸返回几个;
2.targetTouches:正在触摸当前DOM元素上的手指的一个列表;
3.changedTouches:手指状态发生了改变的列表,从无到有,从有到无的变化;
本地存储
特性:
1、数据是存储在浏览器中;
2、设置,读取方便,页面刷新也不会丢失数据;
3、容量大,但是只能存储字符串,可以将对象JSON.stringify()编码后存储;
一、window.sessionStorage
生命周期为关闭浏览器窗口;
在同一个页面,窗口下数据共享;
以键值对形式存储使用;
(1)、存储数据到本地浏览器中;
(window.)sessionStorage.setItem(key, value)
(2)、获取到本地浏览器中存储的数据;
sessionStorage.getItem(key)
(3)、删除数据;
sessionStorage.removeItem(key)
(4)、清空所有浏览器中数据
sessionStorage.clear()
二、window.localStorage
声明周期永久生效,除非手动删除;
同样也是以键值对形式存储数据;
多窗口,页面共享数据;
(1)、存储数据;
localStorage.setItem(key,value)
(2)、查询数据;
localStorage.getItem(key)
(3)、删除数据
localStorage.removeItem(key)
(4)、清空
localStorage.clear()
小实例:
<script> <input type = 'text' id = 'username'> <input type = 'checkbox'>勾选</input> </input> let username = document.querySelector('#username'); let remember= document.querySelector('#remember'); if(localStorage.getItem('username')) { username.value = localSorage.getItem('username'); remember.checked = true } remember.addEventListener('change', function(){ if(this.checked) { localStorage.setItem('username', username.value) } else { localStorage.removeItem('username') } }) </script>
------------------------
JQuery
是一个快速的JavaScript库;
JQuery的基本使用——入口函数
$(function(){
})
或者:
$(document).ready(function(){})
使用方式一:
<body> <script> $(document).ready(function(){ $('div').hide() }) </script> <div></div> </body>
使用方式二:
<body> <div></div> <script> $(function(){ $('div').hide() }) </script> </body>
1、等DOM结构渲染完毕后即可执行内部代码,不必等到所有外部资源加载完成;
2、相当于原生js中的DOMContentLoaded;
3、不同于原生js中的load事件,外部资源文件加载完才执行内部代码;
jQuery的基本使用——顶级对象“$”
“$” 是jQuery的别称,在代码中可以使用jQuery代替;
DOM对象和jQuery对象
1、使用原生js获取到的对象就是DOM对象
let divs = document.querySelector('div')
2、jQuery方法获取的元素就是jQuery对象,其本质就是$对DOM对象包装后产生的对象。
$('div'): 获取到的是jQuery对象
jQuery对象只能用jQuery的方法,
$('div').css('background', 'pink')
DOM对象使用的是原生的js属性和方法;
divs.style.display = 'none'
DOM对象和jQuery对象可以相互转换
1、DOM对象转为jQuery对象
<body> <video src = 'mv.mps'></video> <script> $('video'); let myvideo = document.querySelector('video') myvideo.play(); </script> </body>
(1)、直接获取视频,得到的就是jQuery对象;
2、jQuery对象转为DOM对象(两种方式)
1、$('div')[index] : index是索引号
<video></video> <script> $('video')[0].play() //或者 $('video').get(0).play() </script>
2、$('div').get(index) : index是索引号
jQuery选择器
jQuery基础选择器:$("选择器") //里边选择器直接写css选择器即可,需要加引号
层级选择器:
(1、)子代选择器:
$('ul > li') : 只获取到“儿子”层级元素;
(2、)后代选择器:
$('ul li') : 获取到父级下边所有元素;
jQuery隐式迭代
<div></div> <div></div> <ul> <li></li> <li></li> </ul> <script> //直接获取到元素,然后设置背景 $('div').css('background', 'red') //隐式迭代 $('ul li').css('background', 'red') </script>