JavaScript-jQuery
JavaScript:https://developer.mozilla.org/en-US/docs/Web/JavaScrip
ES6:https://es6.ruanyifeng.com/
MDN:https://developer.mozilla.org/zh-CN/
w3School:https://www.w3school.com.cn/
js中的对象有:内置对象,浏览器对象,自定义对象
a++和++a的区别
/*
a++:a先创建自身的一个副本,然后a自增1,最后返回副本的值。
a=3;b=a++;
运行后 b=3,a=4
++a:将a自增1并返回a。
a=3;b=++a;
运行后 b=4,a=4 */
let n = 0
console.log(n++) //0
console.log(++n)//2
console.log(n);//2
JavaScript基础
变量
-
声明
-
赋值
数据类型
js的变量数据类型,只有在程序运行过程中才能知道数据的具体类型
js是动态语言,变量的数据类型是可以变化的
1、简单数据类型(Number,String,Boolean,Undefined,Null)
- Number数字类型
- NaN :非数值,如果无法计算的返回的就是NaN
- isNaN() :验证是否是数字 ,返回true或false
-
String字符串类型
- 转义符都是以开头: ,\,',", ,
- str.length:字符串长度
- str+任何数据类型 :结果都是拼接好的字符串
-
Boolean布尔类型:ture 或false
-
Undefined未定义类型:一个变量声明,但是没有赋值
-
Null空值:number+null=number本身
2、复杂数据类型(Object)
判断数据类型
-
typeof xx :返回结果只能有string,number,boolean,undefined,function,object
-
A instanceof B 可以判断A是不是B的实例 :返回结果true/false
-
Object.prototype.toString.call(xx)
-
对象的constructor判断:xx.constructor === Date/Function/Array...
-
Jquery提供的
-
jQuery.isArray();是否为数组
-
jQuery.isEmptyObject();是否为空对象 (不含可枚举属性)。
-
jQuery.isFunction():是否为函数
-
jQuery.isNumberic():是否为数字
-
jQuery.isPlainObject():是否为使用“{}”或“new Object”生成对象,而不是浏览器原生提供的对象。
-
jQuery.isWindow(): 是否为window对象;
-
jQuery.isXMLDoc(): 判断一个DOM节点是否处于XML文档中。
数据类型的转换
转换为字符串
-
String(x)
-
x.toString(x, 10)
-
x+''
转换为数字
-
Number(x)
-
parseInt(x, 10)
-
parseFloat(x)
-
x - 0
-
+x
转换为 boolean
-
Boolean(x)
-
!!x
0,NaN, '', null, undefined 转换为布尔型都是false
补充:
-
解释语言和编译语言
- 解释语言:解释一行执行一行(如JavaScript
- 编译语言:在代码执行前,先编译生成中间代码文件,才去执行代码(如java
-
内存图
- object存储的是地址
- 基本类型存储的是值
- stack和heap
-
深复制和浅复制
- 对于简单类型的数据来说,赋值就是深拷贝
- 对于复杂类型的数据(对象)来说,才要区分浅拷贝和深拷贝。赋值是浅拷贝,拷贝heap内存是深拷贝*
运算符
1.算数运算符
-
+ ,- ,*, /, %,
-
a++(a--)是先执行表百达式后再自增,执行表达式时使度用的是a的原值
-
++a(--a)是先自增再执行表知达示,执行表达式时使道用的是自增后的a
2.比较运算符
< ,>,>=,<=,,!=,=,!==
3.逻辑运算符
-
&&,||,!
-
短路与:表达式1&&表达式2:1真返回2,1假返回1 (一旦发现假就结束,返回假的那个表达式)
-
短命或:一旦发现真就结束,返回真。
4.赋值运算符
=,+=,-=,*=,/=,%=
5.运算符优先级
1)()
2)++ -- !
3)* / % + -
4)> >= < <=
5)== != === !==
6) && ||
7) =
8) ,
if语句
-
if
-
if-else
-
if-else if-else
三元表达式
-
表达式?执行语句1:执行语句2
-
相当于if-else
switch
- 语法:
switch (key) {
case value:
执行语句1
break;
case value2:
执行语句2
break;
default:
break;
}
- 注意:
- key中的值和value是全等
- 如果当前case里面没有break,就不会退出switch,会继续执行下一个case
for循环
for(初始变量;条件表达式;操作符){
循环体
}
while循环
while(条件表达式){
循环体
}
do-while循环
-
先执行一次循环体,再判断条件;如果条件为真,执行循环体,否则就退出
-
语法:
do {
循环体
} while (条件表达式);
continue和 break
- continue:立即跳出本次循环,继续下一次循环
- break: 立即跳出整个循环
函数
1、声明函数:
- function 函数名(){}
- 调用:函数名()
2、return作用:
- 返回函数值
- 终止函数(return语句之后的代码不执行)
3、注意:
- return只能返回一个值(一个数字,数组,对象都可以)
- 如果函数没有return,返回的就是undefined
4、arguments:
- arguments实际上是当前函数的一个内置对象
- arguments存储了传递的所有实参
5、伪数组:不是真正意义上的数组
-
具有数组的length属性
-
按照索引的方式进行存储
-
没有真正数组的一些方法如pop(),push()等
6、函数表达式(匿名函数)
- var 变量名=function(){}
- 调用:变量名()
作用域
1、目的:提高程序可靠性,减少命名冲突
2、全局作用域:在script标签或者js文件中
3、局部作用域(函数作用域):在函数内部
4、全局变量:
- 在全局作用域下的变量
- 浏览器关闭才会销毁,比较占内存资源
5、局部变量:
- 在局部作用域下的变量
- 当程序执行完毕,就会销毁,比较节约内存资源
6、作用域链:
内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 (就近原则)
7、注意:
- 如果没有声明,直接赋值的变量是全局变量
- 块级作用域:{} 【在es6中才出现的的】
预解析
1、预解析:var和function会被提升到当前作用域的最前面
2、分类:
-
变量预解析(变量提升):var 变量=值【相当于:var 变量;变量=值】
-
函数预解析(函数提升):function fn() {}
3、补充
-
函数声明:可以先使用再声明
-
函数表达式:必须先声明再使用
对象
1、创建对象的3种方式:
- 字面量创建对象
- new Object创建对象
- 构造函数创建对象
2、字面量创建对象
*var 对象名={属性名:属性值,...,方法名:function(){}}*
3、new Object创建对象
*var变量名=new Object*
4、构造函数创建对象(可以创建多个对象)
- *构造函数语法:
function 构造函数名() {
this.属性名=属性值;
this.方法名=function(){}
}
-
使用构造函数:new 构造函数名()
-
注意:
-
构造函数名首字母大写
-
利用构造函数创建对象的过程,就是对象的实例化
-
-
new关键字的执行过程:
1)new构造函数可以在内存中创建一个空的对象
2)this就会指向刚才创建的对象
3)执行构造函数里面的代码,给这个空对象添加属性和方法
*4)返回这个对象*
5、使用对象
- 调用对象属性:
-
对象名.属性名
-
对象名['属性名']
- 调用对象方法:
- 对象名.方法名()
6、for-in遍历对象
for(var k in 对象) {
console.log(k)//属性名,方法名
console.log(对象[k])//属性值和方法
}
Math对象(js内置对象)
Math.PI
Math.max(x)
Math.min(x)
Math.floor(x) 向下取值,往最小取
Math.ceil(x) 向上取值,往最大取
Math.round(x) 四舍五入
Math.abs(x) 绝对值
Math.random()*n [0,n)区间的随机数
Math.floor(Math.random()*(m-n+1))+n [n,m]区间的随机数整数
日期对象(js内置对象*)
console.log(new Date());
console.log(new Date('2020-4-11 8:8:8'));
console.log(new Date(2020, 4, 11));
// 获取当前时间戳
console.log(new Date().valueOf());
console.log(new Date().getTime());
console.log(+new Date());
console.log(Date.now());
function formatTime() {
var now = new Date()
var y = now.getFullYear()
var m = (now.getMonth() + 1 + '').padStart(1, '0')
var d = (now.getDate() + '').padStart(1, '0')
var w = now.getDay()
var wArr = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
var week = wArr[w]
var hh = (now.getHours() + '').padStart(1, '0')
var mm = (now.getMinutes() + '').padStart(1, '0')
var ss = (now.getSeconds() + '').padStart(1, '0')
return `${y}-${m}-${d}-${week} ${hh}:${mm}:${ss}`
}
// setInterval(() => {
// console.log(formatTime());
// }, 1000);
/* 案例:倒计时 */
// 天:n/60/60/24
// 时:n/60/60%24
// 分:n/60%60
// 秒: n%60
function countDown(a) {
var now = Date.now()
var inputTime = +new Date(a)
var time = (inputTime - now) / 1000
var d = (parseInt(time / 60 / 60 / 24) + '').padStart(2, '0')
var h = (parseInt(time / 60 / 60 % 24) + '').padStart(2, '0')
var m = (parseInt(time / 60 % 60) + '').padStart(2, '0')
var s = (parseInt(time % 60) + '').padStart(2, '0')
return `${d}天 ${h}:${m}:${s}`
}
console.log(countDown('2020-4-13 18:50:00'));
数组对象(js内置对象)
-
检查是否是数组:
-
数组 instanceof Array :返回true/false
-
Array.isArray(数组):返回true/false
-
-
arr.push(xx) 改变原数组,返回新数组的长度
-
arr.unshift(xx) 改变原数组,返回新数组的长度
-
arr.pop(xx) 改变原数组,返回删除元素
-
arr.shift() 改变原数组,返回删除元素
-
arr.reverse() 改变原数组
-
arr.sort() 改变原数组 【单位数好使,标准写法用下面】
// 升序
arr.sort(function (a, b) {
return a - b
})
// 降序
arr.sort(function (a, b) {
return a - b
})
-
arr.indexOf(x,start) 返回数组中第一个x的索引,如果没有返回-1 【正序查找】
-
arr.lastIndexOf(x) 同上【倒序查找】
-
arr.toString() 把数组转成字符串,逗号分隔每一项
-
arr.join('xx') 把数组转成字符串,xx分隔每一项
-
arr1.concat(arr2,arr3,...) 连接数组,返回新数组
-
arr.slice(begin,end) 返回被截取的新数组
-
arr.splice(start,deleteNumber,add1,add2...) 返回被删除的数组,影响原数组
// 案例:数组去重
function unique(arr) {
var nArr = []
for (var i = 0; i < arr.length; i++) {
if (nArr.indexOf(arr[i]) === -1) {
nArr.push(arr[i])
}
}
return nArr
}
console.log(unique([1, 2, 5, 7, 22, 4, 2, 3, 4]));
字符串对象(js内置对象)
0、基本包装类型:把String,Number,Boolean这些简单数据类型包装成复杂数据类型
1、字符串是不可变的,所以字符串的所有方法都返回 一个新的字符串
-
str.length
-
str.indexOf(x,start) 从start开始查找,返回str中x第一次出现的索引,没有返回-1
-
str.charAt(index) 返回索引为index的字符
-
str.charCodeAt(index) 返回索引为index的字符的ASCII码
-
str[index] 返回索引为index的字符
-
str.concat(str1,str2...) 拼接字符串
-
str.substr(start, length) 截取字符串,从start截取length个
-
str.slice(start, end) 截取字符串,从start到end-1,end取不到
-
str.substring(start,end) 截取字符串,从start到end-1,end取不到。不接受负值
-
str.replace('aa','bb') 用bb替换str中的aa
-
str.split("xx") 用xx把字符串分割成数组,每一项用xx隔开
-
str.toLowerCase()
-
str.toUpperCase()
/* 案例:查找字符串中o出现的位置已经次数 */
var str = '1234ididhsidhadjidiii'
var index = str.indexOf('d')
var n = 0
var arr = []
// while (index !== -1) {
// arr.push(index)
// index = str.indexOf('d', index + 1)
// n++
// }
for (var i = 0; i < str.length; i++) {
if (index !== -1) {
arr.push(index)
index = str.indexOf('d', index + 1)
n++
}
}
console.log(n, arr);
console.log(str.charAt(2));
console.log(str.charCodeAt(2));
console.log(str[2]);
/*案例:判断一个字符串中出现最多次数的字符,统计其次数 */
var obj = {}
for (var i = 0; i < str.length; i++) {
console.log(str.charAt(i));
var chars = str.charAt(i)
if (obj[chars]) {
obj[chars]++
} else {
obj[chars] = 1
}
}
console.log(obj);
var max = 0
var ch
for (var k in obj) {
if (obj[k] > max)
max = obj[k]
ch = k
}
console.log(max, ch);
var str2 = 'abcdefG'
console.log(str2.concat('1', 'm', 'a'));
console.log(str2.substr(0, 3));
console.log(str2.slice(0, 3));
console.log(str2.substring(0, 3));
console.log(str2.toLowerCase());
console.log(str2.toUpperCase());
DOM文档对象
获取元素
- document.getElementById("id名")
- element.getElementsByTagName('标签名') 伪数组存储
- document.getElementsByClassName('类名') 伪数组存储
- document.querySelector('选择器') 指定选择器的第一个元素对象
- document.querySelectorAll('选择器') 指定选择器的所有元素对象,伪数组存储
- 获取body元素:document.body
- 获取html元素:document.documentElement
- 补充:console.dir(xx) 打印返回的元素对象,方便查看里面的属性和方法
改变元素内容
- element.innerText 替换起始到终止的内容,去除html标签,空格,换行
- element.innerHTML 替换起始到终止的内容,包括html标签,空格,换行 【用的比较多】
这两个属性是可以读写的,可以获取元素里面的内容
元素属性操作
获取元素属性值
- element.属性 【只能获取内置属性值】
- element.getAttribute('属性') 【可以获取自定义属性值】
设置元素属性并赋值
- element.属性=属性值 【设置内置属性src,href,id,alt,title,type,value,checked,selected,disabled】
- element.setAttribute(属性,属性值) 【设置自定义属性】
删除元素属性
- element.removeAttribute('属性')
H5自定义属性(以 data-xx 格式的自定义的属性)*
-
设置格式:data-xx
-
获取:
-
element.getAttribute('data-xx')
-
element.dataset.xx
-
element.dataset['xx']
-
如果自定义属性有多个-连接(data-lis-name),获取时采用驼峰命名法:element.dataset['listName']
-
元素样式操作
样式属性操作(大小,颜色,位置等)
- element.style.样式名='值' 【行内样式】(如果是background-color这样的用驼峰命名法)
- element.className='className' 【类名样式】(会覆盖原来的类)
- 如果想要保留原来的类名: element.className='className oldClassName1 oldClassName2'
排他思想
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.btnBox {
margin: 20px auto;
100%;
text-align: center;
}
.pink {
background-color: pink;
}
.box {
display: flex;
margin: 0 300px;
border: 4px solid #fff;
}
li {
flex: 1;
list-style: none;
}
img {
100%;
height: 200px;
}
body {
background: url('./img/1.jpg') no-repeat center top;
}
table {
800px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
font-size: 14px;
background-color: #fff;
}
thead tr {
height: 30px;
background-color: skyblue;
}
tbody tr {
height: 30px;
}
tbody td {
border-bottom: 1px solid #d7d7d7;
font-size: 12px;
color: blue;
}
.bg {
background-color: pink;
}
.wrap {
300px;
margin: 100px auto 0;
}
.wrap table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
300px;
}
.wrap th,
.wrap td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.wrap th {
background-color: #09c;
font: bold 16px "微软雅黑";
color: #fff;
}
.wrap td {
font: 14px "微软雅黑";
}
.wrap tbody tr {
background-color: #f0f0f0;
}
.wrap tbody tr:hover {
cursor: pointer;
background-color: #fafafa;
}
</style>
</head>
<body>
<!-- 点击按钮变色 -->
<div class="btnBox">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</div>
<!-- 百度换肤 -->
<ul class="box">
<li><img src="./img/1.jpg" alt=""></li>
<li><img src="./img/2.jpg" alt=""></li>
<li><img src="./img/3.jpg" alt=""></li>
<li><img src="./img/4.jpg" alt=""></li>
</ul>
<!-- 表格经过变色 -->
<table>
<thead>
<tr>
<th>代码</th>
<th>名称</th>
<th>最新公布净值</th>
<th>累计净值</th>
<th>前单位净值</th>
<th>净值增长率</th>
</tr>
</thead>
<tbody>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
</tbody>
</table>
<!-- 表单全选和取消全选 -->
<div class="wrap">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id="j_cbAll" />
</th>
<th>商品</th>
<th>价钱</th>
</tr>
</thead>
<tbody id="j_tb">
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPhone8</td>
<td>8000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPad Pro</td>
<td>5000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPad Air</td>
<td>2000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Apple Watch</td>
<td>2000</td>
</tr>
</tbody>
</table>
</div>
<script>
/* 案例:点击按钮变色 */
var btns = document.querySelectorAll('button')
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
// 去掉其他人,只设置我自己
for (var i = 0; i < btns.length; i++) {
btns[i].className = ''
}
this.className = 'pink'
}
}
/* 案例:百度换肤 */
var imgs = document.querySelectorAll('img')
for (var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function () {
document.body.style.backgroundImage = `url(${this.src})`
console.log(this.src);
}
}
/* 案例:表格经过变色 */
var tbody = document.querySelector('tbody')
var trs = document.querySelectorAll('tr')
for (var i = 0; i < trs.length; i++) {
trs[i].onmouseover = function () {
this.className = 'bg'
}
trs[i].onmouseout = function () {
this.className = ''
}
}
/* 案例:表单全选和取消全选 */
var all = document.querySelector('#j_cbAll')
var others = document.querySelector('#j_tb').querySelectorAll('input')
all.onclick = function () {
for (var i = 0; i < others.length; i++) {
others[i].checked = this.checked
}
}
for (var i = 0; i < others.length; i++) {
others[i].onclick = function () {
var flag = true
// 检查是否全部都选中,全选中all就是true,否则就是false
for (var i = 0; i < others.length; i++) {
if (!others[i].checked) {
// all.checked = false
flag = false
break
}
}
all.checked = flag
}
}
</script>
</body>
</html>
获取节点
节点:nodeType节点类型,nodeName节点名称,nodeValue节点值*
- 元素节点:nodeType=1
- 属性节点:nodeType=2
- 文本节点:nodeType=3 (包括文字,空格,换行等)
父节点: node.parentNode 亲父亲(如果找不到返回null)
子节点
- node.childNodes 所有子节点,包括文本节点元素节点
- node.firstChild 第一个子节点
- node.children 所有子元素节点
- node.firstElementChild 第一个子元素节点
- node.lastElementChild 最后一个子元素节点
- node.children[0] 第一个子元素节点
- node.children[node.children.length-1] 最后一个子元素节点
兄弟节点
- node.nextSibling 下一个兄弟节点
- node.nextElementSibling 下一个兄弟元素节点
- node.previousSibling 前一个兄弟节点
- node.previousElementSibling 前一个兄弟元素节点
节点操作
创建节点
- document.createElement('tagName')
添加节点
- node.appendChild(child) 在node节点中的末尾 添加child
- node.insertBefore(child, 指定元素) 在node节点中的指定元素前面 添加child
删除节点
- node.removeChild(child) 删除node节点中的child节点,返回删除节点
复制节点
- node.cloneNode() 只复制节点本身
- node.cloneNode(false) 只复制节点本身
- node.cloneNode(true) 复制节点本身和子节点
三种动态创建元素的区别
- document.write(xxx) 如果文档流执行完毕,它会导致页面重绘
- element.innerHTML=xxx 【创建多个效率更高,采用数组形式拼接】
- document.createElement('tagName') 【创建多个效率稍低,但结果清晰】
事件
-
事件三要素:事件源,事件类型,事件处理程序
-
注册和删除事件
-
传统方式【能绑定一个事件】
//注册 element.on事件类型=function(){} //删除 element.on事件类型=null
-
监听注册方式【 可以绑定多个事件,常用】
//注册 (第三个参数可有可无,默认false。false在冒泡阶段调用事件处理程序,true在捕获阶段调用事件处理程序) element.addEventListener('事件类型', fn,true/false) function fn() {} //删除 element.removeEventListener('事件类型',fn)
-
只有ie9以前才支持
//注册 element.attachEvent('on事件类型', fn) function fn() {} //删除 element.detachEvent('on事件类型',fn)
-
-
DOM事件流的3个阶段
-
捕获阶段: element.addEventListener('事件类型', fn,true)
-
当前目标阶段
-
冒泡阶段 element.addEventListener('事件类型', fn,false)或 element.addEventListener('事件类型', fn)
-
注意: (1 )S代码只能执行捕获或者冒泡中的一个阶段 。(2)传统方式和attachEvent只能得到冒泡阶段
-
事件对象
事件对象的定义:事件对象只有有了事件才会存在,在事件的侦听函数的小括号里面。当成形参看。是系统自动创建的
element.addEventListener('事件类型', function(event) {
console.log(event)
})
//事件对象的名称是自己命名的,常用e
-
事件对象常见属性和方法:
-
1、普通浏览器:
-
e.target 触发事件的对象
- e.type 事件类型
-
e.preventDefault() 阻止默认行为
- e.stopPropagation() 阻止冒泡
-
2、低版本浏览器:
-
e.srcElement 触发事件的对象
- e.returnValue 阻止默认行为
-
e.cancelBubble 阻止冒泡
-
【传统方式return false 也可以阻止默认行为,return后面的代码不执行了】
-
补充:
-
事件里面的this指向的是事件函数的调用者
-
this返回的是绑定事件的对象
-
e.target或e.srcElement 触发事件的对象
-
事件委托
事件委托核心原理:给父节点添加侦听器,利用事件冒泡影响每一个子节点
常用鼠标事件和鼠标事件对象
-
鼠标事件:
-
click
-
mouseover(鼠标经过自身盒子会触发,进过子盒子也会触发。会冒泡)
-
mouseout
-
mouseenter(只会经过自身盒子触发。不会冒泡)
-
mouseleave(不会冒泡)
-
focus
-
blur
-
mousemove
-
mouseup
-
mousedown
-
// 禁止鼠标右键菜单
document.addEventListener(' contextmenu', function (e) {
e.preventDefault()
})
//禁止鼠标选中
document.addEventListener('selectstart', function (e) {
e.preventDefault()
})
-
鼠标事件对象
- e.clientX 可视区域
- e.clientY
- e.pageX 文档页面
- e.pageY
- e.screenX 电脑屏幕
- e.screenY
常用键盘事件和键盘事件对象
键盘事件:
- keyup
- keydown
- keypress
- 执行顺序:keydown,keypress,keyup
// 键盘事件
document.addEventListener('keyup', function (e) {
console.log('keyup');
})
document.addEventListener('keydown', function (e) {
console.log('keydown');
})
//keypress不识别功能键,如ctrl,shift等
document.addEventListener('keypress', function (e) {
console.log('keypress');
})
//keyup,keydown事件不区分字母大小写
键盘事件对象
- keycode 返回该键的ASCII码
- keyup,keydown事件不区分字母大小写
BOM浏览器对象
window常见事件
1、窗口加载事件:
//load事件 是等页面全部加载完毕(包括dom元素,img,flash,css等;
// window.onload=function() {}
window.addEventListener('load',function() {})
// DOMContentLoaded事件 是dom加载完毕
window.addEventListener('DOMContentLoaded',function() {})
- load事件 是等页面全部加载完毕(包括dom元素,img,flash,css等;
- DOMContentLoaded事件 是dom加载完毕
2、调整窗口大小事件
//window.onresize=function(){}
window.addEventListener('resize', function () {})
- window.addEventListener('resize', function () {}) 或 window.onresize=function(){}
定时器
1、 setTimeout
setTimeout(() => {},延迟时间)
clearTimeout(定时器名字) 清除定时器
2、 setInterval
setInterval(() => { }, 间隔时间)
clearInterval(定时器名字) 清除定时器
3、如果第二个时间参数不写,默认是0(单位是毫秒)】
this指向
- 一般情况下,this指向的是调用它的对象
- 全局作用域或者普通函数中的this指向全局对象window
- 定时器里面的this指向window
- 对象方法中的this指向调用该方法的对象
- 构造函数中的this指向构造函数的实例
- 事件中的this,指向的是绑定事件的对象
URL
- 格式 :protocol://host[:port]/path[?query]#fragment
- 协议
- 主机(域名)
- 端口号
- 路径:由0个或者多个/ 隔开
- 参数:以键值对形式,通过&符号分隔
- 片段:常见链接或锚点
location对象
- location.href 整个URL【常用】
- location.host
- location.port
- location.pathname
- location.search 参数【常用】
- location.hash 片段
- location.assign('path') 跳转页面
- location.replace('path') 替换当前页面,无历史记录
- location.reload() 重新加载页面【location.reload(true)强制刷新】
navigator对象
// 判断用户是那个终端打开,实现跳转
if ((navigator.userAgent.match(
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
))) {
window.location.href = ""; //手机
}else{
window.location.href = ""; //电脑
}
history对象
- hisory.back()
- hisory.forward()
- hisory.go(n)
元素偏移量offset
1、【以带有定位的父级为准,如果没有父级或者父级无定位,就相当于body】
- element.offsetTop
- element.offsetLeft
2、【padding+border+width/height 返回数值无单位】
- element.offsetWidth
- element.offsetHeight
3、返回带有定位的父亲,否则返回body
- element.offsetParent
4、offset和style区别
- 获取元素大小和位置:element.offsetWidth/offsetHeight 【padding+border+widht 返回数值,只可读】
- 元素改变大小:element.style.width/height 【width 返回有单位的字符串,可读可赋值】
元素可视区client
- element.clientTop【上边框的大小】
- element.clientLeft【左边框的大小】
- element.clientWidth【padding+width 返回数值】
- element.clientHeight 【padding+height 返回数值】
元素滚动scroll
-
element.scrollTop 【元素被卷去的上侧距离,返回数值】
-
element.scrollLeft 【元素被卷去的左侧距离,返回数值】
注意:(scrollTop 和scrollLeft一般在scroll事件中获取)
-
element.scrollWidth 【真正的内容width+padding,返回数值】
-
element.scrollHeight 【真正的内容height+padding,返回数值】
补充:
- 页面被卷去的头部:window.pageYOffset
- 页面被卷去的左侧:window.pageXOffset
- 返回顶部:window.scroll(0,0)
立即执行函数
-
格式:(function(){})()或(function(){}())
-
作用:创建一个独立的作用域,避免命名冲突
-
补充:
- dpr物理像素比:window.devicePixelRatio
- pageshow是重新加载页面触发的事件,这个事件是给window添加的
- 如果是从缓存取过来的页面:那么pageshow事件中的e.persisted返回的是true
移动端
触摸事件
- touchstart
- touchmove
- touchend
触摸事件对象
- e.touches 当前触摸屏幕的所有手指列表
- e.targetTouches 当前手指触摸的列表
- e.targetTouches[0] 当前触摸元素的第一个手指的相关信息
- e.changedTouches 手指状态发生了改变列表,无到有或有到无
- 移动端拖动原理:盒子原来的位置+手指移动的距离
- 手指移动的距离:手指滑动后的位置-手指刚开始触摸的位置
解决移动端延迟3毫秒
//使用fastclick :
//1、引入js
//2、在点击事件之前写入:
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body);
}, false);
}
//3、正常注册点击事件
*移动端插件
移动端框架
- Bootstrap (https://www.bootcss.com/)
- Vue (https://cn.vuejs.org/)
- React (https://react.docschina.org/)
- Angular
classList 返回元素的类名
element.classList.add('className') 添加类名 是在后面追加类名不会覆盖以前的类名
element.classList.reomve('className') 删除类名
element.classList.toggle('className') 切换类
本地存储
sessionStorage
- 存储数据 sessionStorage.setItem('key',value)
- 获取数据 sessionStorage.getItem('key')
- 删除数据 sessionStorage.removeItem('key')
- 清空所有数据 sessionStorage.clear()
localStorage
- 存储数据 localStorage.setItem('key',value)
- 获取数据 localStorage.getItem('key')
- 删除数据 localStorage.removeItem('key')
- 清空所有数据 localStorage.clear()
JavaScript高级
对象和类
1、创建类
//类名,首字母大写
class Star {
constructor(uname, age) {
this.uname = uname
this.age = age
}
sing(a) {
console.log("我的作品:", a);
}
}
2、利用类创建对象
var wyf = new Star('kris', 29)
console.log(wyf.uname, wyf.age);
wyf.sing('july')
3、类的继承
// class Son extends Father{} 【Son类继承了Father类里面的方法和属性】
// sper 可以调用父类的构造函数或普通函数;super必须在子类this之前调用
// 继承中的属性和方法查找原则:就近原则
// 类里面共有的属性和方法一定要加this
class Father {
constructor(x, y) {
this.x = x
this.y = y
}
sum() { console.log(this.x + this.y); }
money(a) { console.log(a)}
say() { console.log("我是father")}
}
class Son extends Father {
constructor(x, y) {
super(x, y) //super调用了父类里面的构造函数
this.x = x
this.y = y
}
say() {
console.log("我是son")
super.say() //super调用了父类里面的普通函数
}
substract() { console.log(this.x - this.y); }
}
var ss = new Son(10, 20)
ss.money(100)
ss.sum()
ss.say()
ss.substract()
4、类中this的指向
constructor里面的this指向创建的实例化对象
类中方法的this指向 调用该方法的对象
构造函数和原型
利用构造函数创建对象
// 利用构造函数创建对象
function Star(name, age) {
// 实例成员:构造函数内部通过this添加的成员,如name,age等
// 实例成员只能通过实例化的对象来访问
this.name = name
this.age = age
this.sing = function (a) {
console.log(a);
}
}
/* new在执行时会做4件事情:
1、在内存中创建一个新的空对象
2、让this指向这个空对象
3、执行构造函数里面的代码,给这个新对象添加属性和方法
4、返回这个新对象(所以构造函数里面不需要return)
*/
var wyf = new Star('kris', 29)
console.log(wyf.name, wyf.age);
wyf.sing('july')
// 静态成员:在构造函数身上直接添加的成员
// 静态成员只能通过构造函数来访问
Star.sex = "男"
console.log(Star.sex);
/* 构造函数原型对象prototype
原型对象的作用:共享方法
公共属性定义到构造函数里面,公共方法放在原型对象身上
对象身上系统自己添加一个__proto__属性,指向构造函数的原型对象【对象.__proto__ === 构造函数.prototype】
方法查找规则:先去对象找,如果没有去构造函数原型对象prototype上找
*/
// console.dir(Star);
Star.prototype.eating = function () {
console.log("我在吃饭");
}
// Star.prototype = {
// constructor:Star,
// movie: function () {
// console.log('movie');
// },
// drink: function () {
// console.log("drink");
// }
// }
wyf.eating()
console.log(wyf);
console.log(wyf.__proto__ === Star.prototype);
console.log(Star.prototype);
console.log(Star.prototype.__proto__ === Object.prototype);
console.log(Object.prototype.__proto__);
console.log(wyf.toString());
构造函数中的this指向
- 构造函数中的this指向对象实例.
- 构造函数中方法中的this指向调用该方法的对象.
- 原型对象函数中的this指向对象实例.
扩展内置对象
// 扩展内置对象
console.dir(Array.prototype);
Array.prototype.sum = function () {
var sum = 0
for (var i = 0; i < this.length; i++) {
sum += this[i]
}
return sum
}
var arr = [1, 2, 3, 4]
console.log(arr.sum());
构造函数的继承
// 借用call()继承父类中的属性
function Father(name, age) {
this.name = name
this.age = age
}
function Son(name, age, sex) {
Father.call(this, name, age)
this.sex = sex
}
var son = new Son('kris', 29, '男')
console.log(son);
// 借用原型对象继承父类中的方法
Father.prototype.money = function () {
console.log("money");
}
son.prototype=new Father()
Son.prototype.constructor=Son
Son.prototype.home = function () {
console.log("home");
}
数组新增方法
- forEach()
- map()
- filter() 返回新数组
- some() 返回ture/false 找到第一个满足条件的就终止循环
- every() 返回ture/false
- reduce()
字符串新方法
- str.trim() 去除字符串两边的空格
对象方法
定义新属性或修改属性
Object.defineProperty(对象,'属性名',{
value:属性值,
writable:true, //是否允许重写
enumerable:true,//是否可以被枚举 (默认false,false不允许被遍历)
configurable:true//是否可以被删除或修改特性(默认false,false不允许被删除)
})
函数进阶
函数定义
- 自定义函数:function fn()
- 数表达式(匿名函数):var fun = function () {}
- 利用new Function('参数1','参数2','函数体')
函数调用
- fn()
- fn.call()
- 对象.函数名()
- 立即执行函数
this指向
- 普通函数中的this指向window
- 对象中的方法的this指向调用该方法的对象
- 构造函数中的this指向实例对象
- 构造函数的原型对象上的方法指向实例对象
- 绑定事件中的this指向函数的调用者
- 定时器里面的this指向window
- 立即执行函数里面的this指向window
改变函数内部 this指向
fn.call(thisArg,参数1,参数2,...) 调用fn,同时把fn中的this指向thisArg
fn.apply(thisArg,[参数1,参数2,...]) 调用fn,同时把fn中的this指向thisArg,apply只能传递数组(或者伪数组)
fn.bind(this.Arg,参数1,参数2,...) 不调用fn,fn中的this指向thisArg,返回原函数this指向改变之后一个新函数
// 求数组中的最大值
var arr = [1, 33, 4, 6, 7, 9, 10]
console.log(Math.max(...arr));
// apply可以用来求数组中的最大值
console.log(Math.max.apply(Math, arr));
严格模式
-
开启严格模式:"use strict" 【放在script的最前面或者函数中的最前面】
-
变化:
-
变量必须先声明再使用
-
已经声明的变量不能删除
-
全局作用域下函数中的this是undefined
-
构造函数不加new调用 ,this会报错
-
函数中不能有重名的形参
-
不允许在非函数块声明函数
-
高级函数:把函数作为形参或者返回值的函数
闭包
- 定义:一个函数(作用域)访问了另一个函数中的局部变量,这个局部变量所在的函数称为闭包
- 作用:延伸了变量的作用范围
- 补充:立即执行函数也称为小闭包
递归函数
- 函数内部自己调用自己,这个函数就是递归函数
- 递归里面必须加退出条件
浅拷贝和深拷贝
浅拷贝
Object.assign(target,...被拷贝对象)
深拷贝
-
封装函数:
function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if (obj && typeof obj === "object") { for (key in obj) { // obj.hasOwnProperty("属性")返回true/false,判断obj是否包含特定的自身(非继承)属性 if (obj.hasOwnProperty(key)) { // 判断 obj 是否是对象,如果是,递归复制 if (obj[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key]); } else { // 如果不是 objClone[key] = obj[key]; } } } } return objClone } function deepClone2(newObj, oldObj) { for (var k in oldObj) { var item = oldObj[k] // 判断属性值的数据类型 if (item instanceof Array) { newObj = [] deepClone2(newObj[k], item) } else if (item instanceof Object) { newObj = {} deepClone2(newObj[k], item) } else { newObj[k] = item } } } var o2={} deepClone2(o2,obj) console.log(o2);
-
JSON.parse(JSON.stringify(被拷贝对象))
-
$.extend(true, target, 被拷贝对象);
正则表达式
作用:表单验证,替换敏感词,提取相关内容
创建正则表达式:
- var xx=/表达式/
- var xx=/表达式/
测试正则表达式:
- 正则表达式.test(要测试的str)
特殊字符:
abc 包含abc就可以
^abc 必须以abc开头
^abc$ 必须是abc
[abc] 包含三个中的任何一个
^[abc]$ 必须是三个中的任何一个
^[a-z]$ 必须是26个小写字母中的任何一个
^[a-zA-Z]$ 必须是26大小写个字母中的任何一个
^[a-zA-Z0-9]$ 必须是26大小写个字母,0-9数字中的任何一个
^[a-zA-Z0-9_-]$ 必须是26大小写个字母,0-9数字,_,- 中的任何一个
^[^a-zA-Z0-9_-]$ 不能是26大小写个字母,0-9数字,_,- 中的任何一个 【中括号里面的^表示取反】
[0-9] 包含0-9中的任何一个
* 重复 >=0次
+ 重复 >=1次
? 重复0或1次
{n} 重复n次
{n,} 重复 >=n次
{n,m} 重复n到m次
d 就是 [0-9]
D [^0-9]
w [a-zA-Z0-9]
W [^a-zA-Z0-9]
s [
vf] 换行符,制表符,空格符
S [^
vf]
| 表示或
替换: str.replace(str1或正则表达式,str2)
/表达式/g 全局匹配
/表达式/i 忽略大小写
/表达式/gi 全局匹配+忽略大小写