Javascript
- JavaScript没有访问系统文件的权限
- 由于JavaScript无需编译,是由上到下依次解释执行,所以在保证可读性的情况下,允许使用链式编程
- JavaScript和Java没有任何直接关系
JS的组成
-
ECMAScript(核心):规定了JS的语法和基本对象
-
DOM文档对象模型:处理网页内容的方法和接口
标记型文档,html
-
BOM浏览器对象模型:与浏览器交互的方法和接口
JS的引入方式
js中使用单引号,html使用双引号
(1)内嵌脚本
<input type="button" value="button" onclick="alert('xxx')" />
(2)内部脚本
<script type="text/javascript">
alert("xxx");
</script>
(3)外部脚本
首先先创建一个js文件
其次在html中引入
<script type="text/javascript" src="demo1.js"></script>
标签内部不能有script代码,即使写了也不会执行
注:放在哪都行,但是在不影响html功能的前提下,越晚加载越好,但在body结束之前
注释
单行 ctrl + /
多行 shift + alt +a
输入输出语句
输出
JavaScript 可以接收用户的输入,然后再将输入的结果输出:
alert()
、document.wirte()
、console.log()
以数字为例,向 alert()
或 document.write()
输入任意数字,他都会以弹窗形式展示(输出)给用户。console.log()是控制台输出语法 程序员看的
输入
向 prompt()
输入任意内容会以弹窗形式出现在浏览器中,一般提示用户输入一些内容。
<script>
// 1.document 文档的意思 write 写
document.write('我愿意')
document.write('<h1>我愿意</h1>')
// 2. alert 警示
// alert('黑马')
// 3. 控制台输出语法 程序员看的
console.log('我是用来测试的')
// 4. 输入语句 prompt
prompt('您今年多大了?')
</script>
变量
<script>
var a;//undefined
// alert(a);
alert(b);//有错误停止代码
</script>
- 字母下划线$开头
- 严格区分大小写
- 不能使用关键字
- 不能包含空格
只声明不赋值,undefined
不声明不赋值,报错
不声明只赋值,全局变量
基本数据类型
JS是动态语言,数据类型可以变化
typeof
检测变量数据类型
// 返回的什么类型 string number Boolean null
console.log(typeof 123)
console.log(typeof '123')
console.log(typeof true)
console.log(typeof undefined)
console.log(typeof null)
(1)number:数字类型
(2)string:字符串类型“”和‘’都是字符串。JavaScript中没有单个字符
(3)boolean:布尔类型
(4)null:空类型,一个占位符
(5)underfind:未定义
注意:number、boolean、string是伪对象,undefined==null
JavaScript区别于Java,变量的使用不用严格遵循类型,null返回object(属于历史遗留bug)
数字类型
012的0代表八进制,0x代表十六进制
number.MAX_VALUE代表最大值
Infinity代表无穷大,NaN代表一个非数字
isNaN()用来判断非数字
字符串型
单双引号可以嵌套
.length可以判断字符串长度
字符串拼接 可以字符串+任何类型 = 字符串
数据类型转换
转换字符串型
toString()
String()
+拼接
转换数字类型
parseInt()
parseFloat()
如果有字母会舍去
Number()
隐式转换
// 区别:
// 1.Number() 只能放数字类型的字符,不能放abc这样的
// 否则返回的是 NaN not A number
console.log(Number('10.01abc'))
// parseFloat 经常用于过滤px单位
// console.log(parseFloat('10.01abc'))
console.log(parseFloat('100px'))
// console.log(parseFloat('px100px'))
// let num = prompt('请输入一个数字')
// console.log(num, typeof num)
// 内部悄悄的把 18 转换为了字符串的 '18'
console.log('pink老师' + 18)
console.log(10 + '10') // 1010
// - * / 把 字符串的 '10' 转换为 数字型 10
console.log(10 - '10') // 0
// 小技巧
let num = '10'
console.log(num)
console.log(+num)
// console.log(-num)
console.log(10 + +'10')
布尔型转换
Boolean()
false: 0,Nan,null,undefined
运算符
算数运算符
+: 遇到字符串变成连接
-:先把字符串转成数字然后进行运算
*: 先把字符串转成数字然后进行运算
/: 先把字符串转成数字然后进行运算
递增
++num,先加后返回值
num++,先返回值,后加
比较运算符
== :有隐式转换
===:全等:类型与值都要相等
!==:值相同,类型是否不相同
正则对象
- var reg = new RegExp(“表达式”)
- var reg = /^表达式$/ //直接量表达
- var reg = /\s/; //普通方式创建
普通方式:只要有一个字符符合正则就返回true
逻辑运算
逻辑中断
123 && 456 返回456
123 || 456 返回123
0 || 456 || 789 返回456
案例
var num = 0;
console.log(123 || num++);
console.log(num);
运算符优先级
优先级 | 运算符 | 顺序 |
---|---|---|
1 | 小括号 | () |
2 | 一元运算符 | ! ++ – |
3 | 算数运算符 | 先* / % 后+ - |
4 | 关系运算符 | > >= < <= |
5 | 相等运算符 | == , != , === , !== |
6 | 逻辑运算符 | 先&& 后== |
7 | 赋值运算符 | = |
8 | 逗号运算符 | , |
表达式
条件表达式
条件表达式 ? 表达式1 :表达式2
真的就返回表达式1,假返回表达式2
let re = num1 > num2 ? num1 : num2
switch
<script>
// 1. 用户输入数字 还有一次 运算符
let num1 = +prompt('请您输入第一个数:')
let num2 = +prompt('请您输入第二个数:')
let sp = prompt('请您输入+ - * / 运算')
// 2. 根据不同的运算符计算不同的结果 switch
switch (sp) {
case '+':
alert(`您选择的是加法,结果是: ${num1 + num2}`)
break
case '-':
alert(`您选择的是减法,结果是: ${num1 - num2}`)
break
case '*':
alert(`您选择的是乘法,结果是: ${num1 * num2}`)
break
case '/':
alert(`您选择的是除法,结果是: ${num1 / num2}`)
break
default:
alert(`你输了啥? 请输入+ - * / `)
}
</script>
JavaScript数组对象
js数组的特性:可以看成Java中的ArrayList集合
- 数组中的每一个成员没有类型限制,可以存放任意类型
- 数组的长度可以自动修改
四种创建方式:
- var arr1 = [1, 2, 3, “a”, true]; //常用的js数组
- var arr2 = new Array(); //数组长度默认为0
- var arr3 = new Array(4); //数组长度是4的空间,每个元素是undefined(没必要
- var arr4 = new Array(1, 2); //数组元素是1,2(没必要
扩容e
修改length长度,然后追加新增元素,否则显示为undefinded
不要直接给数组赋值,否则数组元素会直接抹除
常用属性/方法:
- length:数组长度
- join():把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔一个
- toString():转换成字符串以逗号分隔
var arr = ['a', 'b', 'c', 'd']
var result = arr.join("+")
alert(result) //a+b+c+d
- reverse():反转数组,对元素下标进行互换
- pop():删除并返回最后元素
- push():向数组的末尾添加一个或更多元素,并返回新的长度
- indexOf(): 返回元素的索引值
全局函数
- eval():将字符串当作脚本进行解析运行
- encodeURI():把字符串编码为URI
- decodeURI():解码某个编码的URI
URI:统一资源标识符,标识了资源详细名称
URL:统一资源定位器,定位资源的网络位置
注:
- 如果某个字符从字面值无法转,则从该字符停止转换
- 如果第一个字符就无法转换,则输出NaN(not a number),是一个标识,专门标识当前的值不是数字
自定义函数
function 函数名(参数列表){函数体}
JavaScript的函数没有重载只有覆盖,即使实参和与函数的形参不匹配,也不会影响正常调用,如果形参未赋值,就使用默认值undefined。
<script>
function getSum(a, b) {
return a + b;
}
var result = getSum(1, 2)
alert(result)
</script>
实参和形参个数不匹配
多于形参,则会选取前n个实参
少于形参,则会认为是undefinded
return
return 只会返回一个值,并且只返回最后一个
如果要返回多个,可以使用数组
arguments
存储了所有的实参,
伪数组
具有数组的长度、索引,但没有数组对应的pop,push
作用域链
就近原则
立即执行函数
(function (x, y) {
console.log(x + y)
})(1, 2)
预解析
1、预解析js引擎会把所有的var和function提升到当前作用域的最前面
2、代码从上往下执行
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
变量预解析只提升声明,不解析赋值
自定义对象
JavaScript中的引用数据类型都是对象,而对象在JavaScript中可以用函数来表示。
<script>
// 利用对象字面量创建对象
var obj = {};
var obj = {
uname: "张三丰",
age: 18,
sayhi: function(){
console.log('hello');
}
}
// 调用属性,以下方法均可
console.log(obj.name);
console.log(obj[name])
//1.构造参数赋值
//2.创建对象后,调用属性进行赋值
//3.直接创建对象及属性
function Person1() {
this.name = "xiaozhang"
this.age = "18"
}
var p = new Person1()
alert(p.name)
alert(p.age)
function Person2(n, a) {
this.name = n
this.age = a
}
var p = new Person2("xiaowang", "20")
alert(p.name)
alert(p.age)
var Person3 = {name:"xiaoli",age:18}
alert(Person.name)
alert(Person.age)
</script>
for in 遍历对象
和python 一样
内置对象
文档:MDN/W3C
Math
方法 | 描述 |
---|---|
PI | 返回 PI(约 3.14) |
exp(x) | 返回 Ex 的值。 |
random() | 返回 0 到 1 之间的随机数。 |
round(x) | 将 x 舍入为最接近的整数。-3.5是-3 |
floor(x) | 返回 x,向下舍入为最接近的整数。 |
ceil(x) | 返回 x,向上舍入为最接近的整数。 |
abs(x) | 返回 x 的绝对值。 |
log(x) | 返回 x 的自然对数。 |
log10(x) | 返回 x 的以 10 为底的对数。 |
Data
var d = new Date();
var d = new Date(milliseconds);
var d = new Date(dateString);
var d = new Date(year, month, day, hours, minutes, seconds, milliseconds);
有参数返回参数时间,无参数返回当前时间
方法 | 描述 |
---|---|
getFullYear() | 返回年份 |
getMonth() | 返回月份(从 0-11)需要+1 |
getDay() | 返回星期几(0-6)周日返回的是0 |
getUTCDate() | 根据世界时,返回月份中的第几天(从 1 到 31) |
now() | 返回自 1970 年 1 月 1 日午夜以来的毫秒数 |
parse() | 解析日期字符串并返回自 1970 年 1 月 1 日以来的毫秒数 |
setDate() | 设置 Date 对象中月的某一天 |
toString() | 将 Date 对象转换为字符串 |
+new Date()返回总的毫秒数
计算天数
d = parseInt(总秒数/60/60/24)
计算小时
d = parseInt(总秒数/60/60%24)
计算分钟
d = parseInt(总秒数/60%60)
计算秒数
d = parseInt(总秒数%60)
instanceof运算符
判断是否为xx, 数组存在isArray
字符串
字符串操作都不会修改原有字符串
indexOf
返回位置,可以添加参数 从第i个开始查询
charAt(index)
charcodeAt(index)
substr(截取的起始位置,截取几个字符)
数据类型传参
复杂数据类型传参会改变实参结果
BOM对象
节点操作
- 元素节点:所有的标签
- 属性节点:比如herf
- 文字节点:所有的文本
- 其他
节点查找
- 父节点:子元素.parentNode
- 子节点:xxx.children
- 兄弟节点:xxx.nextElementSibling
- 追加节点:document.createElement(‘标签名’)
-
父元素.appendChild
- 克隆节点:元素.cloneNode(true)
- 删除节点:父元素.removeChild
let son = document.querySelector('.son')
// 找爸爸
// console.log(son.parentNode)
son.parentNode.style.display = 'none'
// 括号为空则默认为false 如果是false则不克隆后代节点
// 如果是true则克隆后代节点
let newUl = ul.cloneNode(true)
document.body.appendChild(newUl)
时间对象
let date = new Date()
console.log(date)
// 小括号里面写上时间,可以返回指定的时间
let last = new Date('2021-8-29 18:30:00')
console.log(last)
案例
<div></div>
<script>
let arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
let div = document.querySelector('div')
// 先调用,就省去了1秒的空白期
getTime()
setInterval(getTime, 1000)
function getTime() {
// 1. 实例化时间对象 一定写到定时器里面才可以额
let date = new Date()
let year = date.getFullYear()
let month = date.getMonth() + 1
let date1 = date.getDate()
let hour = date.getHours()
let min = date.getMinutes()
let sec = date.getSeconds()
let day = date.getDay()
div.innerHTML = `今天是: ${year}年${month}月${date1}日 ${hour}:${min}:${sec} ${arr[day]}`
}
</script>
时间戳
// 1. getTime()
let date = new Date()
console.log(date.getTime())
// 2. +new Date()
console.log(+new Date()) // 当前的时间戳
console.log(+new Date('2021-8-30 12:00:00')) // 指定时间的时间戳
// 3. 只能得到当前的
console.log(Date.now())
重绘和回流
浏览器是如何进行界面渲染的?
- 解析(Parser)HTML,生成DOM树
- 同时解析CSS,生成样式规则
- 根据DOM树和样式规则,生成渲染树
- 进行布局Layout(回流/重排):根据生成的渲染树,得到节点的几何信息
- 进行绘制iPainting(重绘):根据计算和获取的信息进行整个页面的绘制
- Distplay:展示在页面上
回流
当渲染树中部分或者全部元素的尺寸、结构、布局发生改变的时候,浏览器就会重新渲染部分或全部文档的过程称为回流
重绘
由于节点元素的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline)
重绘不一定引起回流,而回流一定会引起重绘
DOM对象
浏览器自动生成对象
获取元素对象
document.querySelector('')
// 1. js 获取 第一个元素
let div = document.querySelector('div')
let div = document.querySelector('.three')
let li = document.querySelector('ul li:last-child')
- getElementById(); ->通过元素ID获取对应元素对象
- getElementsByName(); ->通过元素的name属性获取符合要求的所有元素
- getElementsByTagName(); ->通过元素的元素名属性获取符合要求的所有元素
- getElementsByClassName(); ->通过元素的class属性获取符合要求的所有元素
<body>
<input type="text" id="t1">
<input type="checkbox" name="hobby" value="read">
<input type="checkbox" name="hobby" value="code">
<input type="checkbox" name="hobby" value="run">
<ul>
<li>javaee</li>
<li>android</li>
<li>ios</li>
<li>php</li>
</ul>
<input type="radio" name="sex" value="man" class="h1">
<input type="radio" name="sex" value="woman" class="h1">
<script>
var t1 = document.getElementById("t1");
alert(t1);
var arr = document.getElementsByName("hobby");
alert(arr.length);
var tar = document.getElementsByTagName("li");
alert(tar.length);
var cla = document.getElementsByClassName("h1");
alert(cla.length);
</script>
修改DOM属性
document.write()
只能追加到body前
<script>
// 1. 获取标签(元素)
let box = document.querySelector('div')
// 2. 修改标签(元素)内容 box是对象 innerText 属性
// 对象.属性 = 值 不识别标签
// box.innerText = '有点意思~'
// box.innerText = '<strong>有点意思~</strong>'
// 3. innerHTML解析标签
box.innerHTML = '<strong>有点意思~</strong>'
</script>
自动更换图片案例
<img src="./images/1.webp" alt="">
<script>
// 1. 获取图片元素
let pic = document.querySelector('img')
// 2. 随机得到图片序号
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
let num = getRandom(1, 6)
// 3. 完成src 属性赋值
pic.src = `./images/${num}.webp`
</script>
修改样式属性
<div> </div>
<script>
// 1. 获取元素
let box = document.querySelector('div')
// 2. 改变背景颜色 样式 style
box.style.backgroundColor = 'hotpink'
box.style.width = '400px'
box.style.marginTop = '100px'
box.className = 'active'
</script>
可以通过操作CSS类来批量修改
- classList.add
- classList.remove
- classList.toggle
切换
表单属性设置
// 1. 获取元素
let input = document.querySelector('input')
// 2. 取值或者设置值 得到input里面的值可以用 value
// console.log(input.value)
input.value = '小米手机'
input.type = 'password'
// 2. 启用按钮
let btn = document.querySelector('button')
// disabled 不可用 = false 这样可以让按钮启用
btn.disabled = false
// 3. 勾选复选框
let checkbox = document.querySelector('.agree')
checkbox.checked = false
定时器
// setInterval(function () {
// console.log('高薪就业')
// }, 1000)
function show() {
console.log('月薪过2万')
}
let timer = setInterval(show, 1000)
// let timer1 = setInterval(show, 1000)
// 清除定时器
clearInterval(timer)
焦点图案案例
// 1. 获取元素 图片 和 h3
let pic = document.querySelector('.pic')
let text = document.querySelector('.text')
// i 记录图片的张数
let i = 0
// 2.开启定时器
setInterval(function () {
i++
// 修改图片的src属性
// console.log(data[i].imgSrc)
pic.src = data[i].imgSrc
// 修改文字内容
text.innerHTML = data[i].title
// 无缝衔接
if (i === data.length - 1) {
i = -1
}
// i === 8 ? i = -1 : i
}, 1000)
JS事件
通常鼠标或热键的动作称之为事件(event),通过js事件,我们可以完成页面的指定特效。
JS事件驱动机制简介
元素.addEventListener(‘事件’,要执行的元素)
- 事件源:专门产生事件的组件
元素
- 事件:由 事件源所产生的动作或者事情
- 监听器:专门处理事件源所产生的事件
- 注册/绑定监听器:让监听器时刻监听事件源是否有指定事件产生,如果事件源产生指定事件,则调用监听器处理
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function run1(){
alert("点了")
}
</script>
</head>
<body>
<input type="button" value="点我啊" onclick="run1()"/>
<!--
事件源:按钮 button
事件:点击事件 onclick
监听器:run1()方法
注册监听器:onclick="run1()"
-->
</body>
案例
<script>
// 1. 获取元素 全选 和 ck 小复选框
let all = document.querySelector('#checkAll')
let cks = document.querySelectorAll('.ck')
let span = document.querySelector('span')
// 2. 事件监听 全选按钮
all.addEventListener('click', function () {
// console.log(all.checked) // true false
// 我们需要做的就是把 all.checked 给下面三个小按钮
// 因为三个按钮在伪数组里面,我们需要遍历的方式,挨着取出来,依次给值
for (let i = 0; i < cks.length; i++) {
cks[i].checked = all.checked
}
// 当我们的全选按钮处于选中状态,则可以改为取消
if (all.checked) {
// console.log('要改')
span.innerHTML = '取消'
} else {
span.innerHTML = '全选'
}
})
// 3. 小按钮的做法 同时给多个元素绑定相同事件
for (let i = 0; i < cks.length; i++) {
// 绑定事件
cks[i].addEventListener('click', function () {
// console.log(11)
// 只要点击任何一个小按钮,都要遍历所有的小按钮
for (let j = 0; j < cks.length; j++) {
// 都来看看是不是有人没有选中
if (cks[j].checked === false) {
// 如果有false 则退出循环 结束函数
all.checked = false
span.innerHTML = '全选'
return
}
}
// 当我们的循环结束,如果代码走到这里,说明没有false,都被选中了,则全选按钮要选中
all.checked = true
span.innerHTML = '取消'
})
}
</script>
高阶函数
如果将函数作为值传给变量那函数称为,回调函数
回调函数和函数表达式都属于 高阶函数
排他思想
// 默认粉色否则会找不到
<button class="pink">第1个</button><button>第2个</button><button>第3个</button><button>第4个</button><button>第5个</button>
<script>
let btns = document.querySelectorAll('button')
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
// this.classList.add('pink')
// 干掉所有人
for (let j = 0; j < btns.length; j++) {
btns[j].classList.remove('pink')
}
// 或者
document.querySelector('.pink').classList.remove('pink')
// 复活我自己
this.classList.add('pink')
})
}
</script>
事件对象
<button>点击</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('mouseenter', function (e) {
console.log(e)
})
</script>
获取事件对象
- type:获取当前事件类型
- clientX:获取光标相对于浏览器可见窗口左上角的位置
- offsetX:获取光标相对于当前DOM元素左上角的位置
- key:用户按下的键盘键的值
事件流
事件流指的是事件完整执行过程中的流动路径
事件冒泡指的是当一个元素触发事件之后,会依次调用所有父级元素的同名事件
<script>
let fa = document.querySelector('.father')
let son = document.querySelector('.son')
fa.addEventListener('click', function () {
alert('我是爸爸')
}, true)
son.addEventListener('click', function () {
alert('我是儿子')
}, true)
document.addEventListener('click', function () {
alert('我是爷爷')
}, true)
// btn.onclick = function() {}
</script>
默认第三个参数是false,冒泡机制
阻止事件流动
e.stopPropagation()
注册事件
传统注册(L0)
- onclick
- 同一个对象后面注册的会覆盖前一个
- 直接实验null覆盖就可以解绑
- 都是冒泡阶段执行
事件监听(L2)
- addEcentListener
- 后面注册的不会覆盖前一个
- 可以通过第三个参数去确定是否在冒泡阶段执行
- 必须使用removeEventListener处理函数
- 匿名函数无法解绑
事件委托
<ul>
<li>我是第1个小li</li>
<li>我是第2个小li</li>
<li>我是第3个小li</li>
<li>我是第4个小li</li>
<li>我是第5个小li</li>
</ul>
<script>
// 不要每个小li注册事件了 而是把事件委托给他的爸爸
// 事件委托是给父级添加事件 而不是孩子添加事件
let ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
// alert('我点击了')
// 得到当前的元素
// console.log(e.target)
e.target.style.color = 'red'
})
</script>