认识JavaScript
html:主要目的搭建页面的结构
css:装饰页面
JavaScript:在用户在页面上的操作有反馈,也叫做用户与页面的交互
- 能够修改css的样式
- 能够操作html
- 能够获取后台数据,把数据展示在页面中
- 可以把信息发送给后台
js和html、css一样都是一个编程语言。运行在浏览器上的编程语言
html、css、js三者分离:结构、行为、样式分离
网页页面加载的顺序
- 地址叫做域名,把域名转化解析成ip地址
- 根据ip地址访问,对应的服务器。(项目)
- 从服务器下载你要访问的页面
- 浏览器加载你的页面
- 先从上到下执行,先会根据html构建网页的结构
- 根据css,渲染样式
代码执行顺序:
代码先预解析,代码从上往下,从左到右,遇到等号,先执行等号右边的
关于前端的引号并没有区分
约定:html属性默认都是双引号、 js默认是单引号
单引号里面套双引号,双引号里面套单引号
js的注释
单行注释 // 快捷键ctrl+/
多行注释 /* */ 快捷键 shift + alt + a
javascript组成部分
ECMAScript:
js的核心语法(变量、函数、条件语句、循环、运算符、数据类型、字符串方法、时间对象、数学对象、数组、json)
什么是ECMA
是一个计算机协会组织,规范制定一些计算机相关的标准(组织、包含、语言类的作者、浏览器厂商)
什么是ECMAScript
ECMA这个组织出了很多标准,其中第262条标准叫做ECMAScript
为什么要规范JS的标准
需要浏览器按照标准去解析
什么是ES4、5、6
是JS的版本
ECMAScript 1.0 1997年出来
ECMAScript 2.0 1998年出来
ECMAScript 3.0 1999年出来 刚开始一年一个版本 最稳定的,被所有浏览器支持
ECMAScript 4.0 2007年 在4.0作者觉得应该让JS功能更丰富,更严谨,需要大幅度的改动JS
ECMAScript 3.1 这个版本是 4.0的阉割版
ECMAScript 5
ECMAScript 6 2007年提出 2015年ES6草案才通过
ES6不是一次性改完,分很多年慢慢改的第一版是2015年发布的,叫ESMA2015这些叫ES6
现在大版本叫ES6,以及ESNext
ECMAScript是有版本的
ECMA4 现在学的,所有浏览器版本都兼容的
ECMA5 从这里开始不兼容IE低版本浏览器
ECMA6
DOM:document object model 文档对象模型
获取元素、修改样式、修改属性、修改文本
主要操作页面里面的所有东西(html css)
BOM: browser object model 浏览器对象模型
三大弹框 : alert(‘内容’) 警告框 .confirm(‘内容’) 确认框 .prompt(‘内容’) 输入框
定时器
js的添加方式
行内引入方式、当作属性去添加
<body>
<button onclick="
document.getElementById('div1').style.width='300px';
document.getElementById('div1').style.height='200px';
document.getElementById('div1').style.background='blue'">
变化
</button>
<div id="div1"></div>
</body>
内嵌引入方式(内部引入)
写在script标签中、可以写在任意地方;
当需要我们在头部引用脚本就放在头部,否则则放在底部,因为放在头部可能会影响浏览器渲染
<script>
// function 函数名{()
// 要执行的代码
//}
// 函数就是装代码的容器
function fn(){
document.getElementById('div1').style.width = '300px';
document.getElementById('div1').style.height = '200px';
document.getElementById('div1').style.background = 'blue'
}
</script>
<body>
<button onclick="fn()">变化</button>
<div id="div1"></div>
</body>
外部引入方式、在script标签中使用src引入外部文件
<script src=" "></script>
变量:
什么是变量 ?
- 一句代码的别名、容器
变量的分类:
全局变量:在函数外面声明的, 只要定义了在任何地方都可以使用,相当于在浏览器占用一个空间,并且浏览器关闭才会释放,会一直占用内 . 全局的变量相当于在浏览器内容中储存了一个内容,并且这个不会释放掉除非浏览器关闭
- var的时候相当于在js的window对象上存了一个属性
- window.上面的东西在使用的时候不需要写window
- BOM里面都是window, 都不用写window
局部变量:在函数内部声明的,在函数内可以使用 ,相当于在函数内占用空间,函数使用完就释放. 局部变量只能在函数的作用域内使用
如果局部变量和全局变量名字相同,如果在函数内部使用,先找函数内部变量,再找全局变量
var 变量名 = 变量值 var a=1 var oDiv=document.getElementById(“ ”) 获取一个元素,把元素赋值给oDiv
变量生命周期
全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。
而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。
为什么他们释放的时机不同的
因为js有一个自动的垃圾回收机制(把没有用的东西释放掉) 需要判别哪些是垃圾。
因为全局变量在任意地方都能使用,所以不会当成垃圾,但是局部变量在函数内部使用,当函数使用完,就可以当做垃圾清除掉。
变量和函数还存在预解析的现象
变量的提升,这种提升的现象叫做预解析
作者在设计代码的时候,想让代码执行的更快一些。所以在最开始的时候,预先把变量的定义提升到当前作用域的最上面。
注意:仅仅是定义,没有赋值。预解析也是有范围的, 好的写代码的方式。把变量的定义都放在最上面
在js刚刚加载之前,会把变量和函数的定义提前,仅仅是定义,没有赋值,并且提升的时候是有作用域的
- 函数开始的时候
- script标签开始的位置
- js文件开始的位置
如何声明 :
变量的命名规范
如何声明: var变量名 = 变量值
官方规定:
- 变量必须以字母、下划线、或者$开头,不能为数字
- 变量中不能出现空格或者其他标点符号
- 不能出现中文
- 不能用关键字、保留字(js出现单词不能用)
命名约定俗成
驼峰命名法(小驼峰命名法:匈牙利命名法)
-
首个单词小写,后面的单词首字母大写
-
变量的类型+名字进行取名
○ oDiv div对象 ○ sValue value的字符串 ○ bFlag 一个真假的值 ○ fnShow 展示函数
名字必须有意义
项目中命名可以拼音,可以英文,但是如果用拼音全部用拼音,如果用英文全部用英文,不允许混合用,不允许缩写用。
声明变量的时候不加var
不加var就是全局变量,哪怕在函数内声明,也是全局变量
注意:声明的时候必须var,为什么不会报错,是js语言设计的缺陷
连等号赋值
var a =b=c=d=1;这种方法不能用,因为b、c、d变成了全局变量
连续赋值 var a=1,b=1,c=1,d=1
for (var i = 0, j = 0; i < 2, j < 5; i++, j++) {
console.log(i, j);
}
代码从左到右执行,判断条件看最右边
ES6里面的声明变量方法
Let / Const/Var
为了解决var的各种各样的问题,出现了Let和Const
Let相对于var 有啥区别
- Let不会变量提升
alert(a);//Cannot access 'a' before initialization 初始化前无法访问
let a=1;
- 相同的变量,在同一作用域内不能重复声明
let a=1;
let a=2; // Identifier 'a' has already been declared 标识符xx已经声明
alert(a);
- 不把全局变量放在window,这样提高性能
var a=1;//相当于把a放进了window。
//这样就会导致window里面的内容非常庞大。使用window里面的东西,性能就不好。
let a=1;
console.log(window);
- 用let会产生块级作用域
//在let之前只有一种作用域 函数作用域,现在用let声明多了一种作用域,块级作用域
//用{}包裹的都有作用域。 for(){} if(){} while(){}
if(true){
let a=1;
}
alert(a);
Const相对于var有啥区别
-
const不会变量提升
-
相同的变量,在同一作用域内不能重复声明
-
不把全局变量放在window,这样提高性能
-
用const会产生块级作用域
const相对于let区别
-
const声明了就不能更改,声明的是常量
-
只要声明了就必须赋值
解构赋值:
等号两边结构一样,常用数组和json对象的解构
let[a,b]=[1,2]
let{a,b}={a:1,b:2}
let [a,{aa},c]=[1,{aa:2},3]
let {a,b}={a:1,b:[1,2,3]}
块级作用域
for 循环举例(经典案例)
for 循环举例(经典案例)
代码 1、我们先来看看如下代码:(用 var 定义变量 i)
<!DOCTYPE html>
<html lang="">
<head>
<meta />
<meta />
<meta />
<title>Document</title>
</head>
<body>
<input type="button" value="aa" />
<input type="button" value="bb" />
<input type="button" value="cc" />
<input type="button" value="dd" />
<script>
var myBtn = document.getElementsByTagName('input');
for (var i = 0; i < myBtn.length; i++) {
myBtn[i].onclick = function () {
alert(i);
};
}
</script>
</body>
</html>
上方代码中的运行效果如下:
为何点击任何一个按钮,弹出的内容都是 4 ?这是因为,我们用 var 定义的变量 i,是在全局作用域声明的。整个代码中,自始至终只有一个变量。
for 循环是同步代码,而 onclick 点击事件是异步代码。当我们还没点击按钮之前,同步代码已经执行完了,变量 i 已经循环到 4 了。
也就是说,上面的 for 循环,相当于如下代码:
var i = 0;
myBtn[0].onclick = function () {
alert(i);
};
i++;
myBtn[1].onclick = function () {
alert(i);
};
i++;
myBtn[2].onclick = function () {
alert(i);
};
i++;
myBtn[3].onclick = function () {
alert(i);
};
i++; // 到这里,i 的值已经是4了。因此,当我们点击按钮时,i的值一直都是4
代码 2、上面的代码中,如果我们改为用 let 定义变量 i:
<!DOCTYPE html>
<html lang="">
<head>
<meta />
<meta />
<meta />
<title>Document</title>
</head>
<body>
<input type="button" value="aa" />
<input type="button" value="bb" />
<input type="button" value="cc" />
<input type="button" value="dd" />
<script>
var myBtn = document.getElementsByTagName('input');
for (let i = 0; i < myBtn.length; i++) {
myBtn[i].onclick = function () {
alert(i);
};
}
</script>
</body>
</html>
上方代码中的运行效果如下:
上面这个运行结果,才是我们预期的效果。我们用 let 定义变量 i,在循环的过程中,每执行一次循环体,就会诞生一个新的 i。循环体执行 4 次,就会有四个 i。
暂时性死区 DTC
ES6 规定:使用 let/const 声明的变量,会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。
也就是说,在使用 let/const 声明变量时,变量需要先声明,再使用(声明语句必须放在使用之前)。这在语法上,称为 “暂时性死区”
DTC 其实是一种保护机制,可以让我们养成良好的编程习惯。
代码举例:
const name = 'qianguyihao';
function foo() {
console.log(name);
const name = 'hello';
}
foo(); // 执行函数后,控制台报错:Uncaught ReferenceError: Cannot access 'name' before initialization
闭包
两个函数定义的时候,出现函数嵌套,这个时候父级函数的局部变量就不会被释放掉,因为不知道子函数什么时候会用,这个时候会造成局部变量无法释放,这种现象叫做闭包。
function fn1( ) {
let a = 10;
function fn2( ) {
console.log(a);
}
fn2( );
}
fn1( );
函数 fn2 的作用域 访问了 fn1 中的局部变量,那么,此时在 fn1 中就产生了闭包,fn1 称之为闭包函数。
闭包缺点:如果有大量的闭包,内存就不会释放掉
解决方法:
- 减少闭包的使用
- 当子函数使用完后,干掉子函数
数据类型:
用typeof分类
-
数字:number
-
字符串:string
-
布尔值:boolean
-
函数:function
-
对象:object 空对象:null typeof的的类型是object
-
未定义:undefined
-
- 声明一个变量为赋值 var a; a就是undefined
- 函数没有传参 function fn(a,b){} a.b就是undefined
- 函数没有返回值) function fn(){} var a =fn() a就是undefined
-
NaN not a number 不是一个数字 typeof 下属于number
-
- NaN非纯数字的字符串或者undefined参与运算,都会得到NaN
- NaN 不等于NaN
- 怎么判断是不是NaN isNaN(要判断的东西)
基础数据类型
number string boolean null undefined NaN
引用数据类型
对象 函数
常见的对象(数组、json、时间对象、数学对象、正则对象)
基础数据类型和引用数据类型区别
存储方式不同
基础数据类型因为他简单,占用空间少。所以他是直接指向储存的数字
var a=1; a直接代表1 名字直接对应了一个个体
复杂数据类型,因为他的里面会放很多的简单数据类型,占用的空间大。名字对应的是一个地址
var arr=[1,2,3,4,5];
注意事项:
1、引用数据类型复制的时候比较麻烦。 建议暂时用…
2、引用数据类型的比较,哪怕两个东西完全一样,也不相同
数据类型之间的转换和真假的关系
字符串转成数字
隐式类型转换: - / * % == != 运算做了隐式转换
强制类型转换:隐式类型转换变化太多,容易出现错误
-
parseInt(字符串)调用的结果就是转化的整数
-
‘18’ 18
-
‘18.1’ 18
-
‘18a’ 18
-
‘a18’ NaN
-
-
parseFloat(字符串) 调用的结果是转化的小数
-
‘18’ 12
-
‘18.1’ 12.1
-
‘18a’ 12
-
‘a18’ NaN
-
-
Number(字符串) 调用的结果就是转化的数字,字符串里面必须全部都是数字
-
‘18’ 18
-
‘18.1’ 18.1
-
‘18a’ NaN
-
‘a18’ NaN
-
转换错误会出现NaN(not a number )
数字转化成字符串
数字 + " "
js里面的真假关系
在js里面只有6个假,除此之外都是真
- 0
- false
- 空字符串‘’(‘空格’不是)
- NaN
- null
- undefined
js的输入输出方式
alert( ) 、 console.log( )、prompt 最主要目的是为了测试
三种弹框
页面弹窗alert()
- 只是消息的提示,能中断代码。
- alert()展示的数据都会被转化成字符串
- 只能打印一个东西
输入弹窗prompt(‘ ’)
- 可以让用户输入的提示框
- 也会中断代码
- 会返回结果,返回的结果是字符串
判断弹窗confirm(‘ ’)
可以用户选择确定还是取消,会返回一个true false的结果
var b = "刘帅是不是帅二娃";
confirm(b);
控制台输出 console.log()
- 不会中断代码
- 不会转换类型
- 可以打印多个,用逗号隔开
var a = NaN;
console.log(isNaN(a));
输出写在页面中的document.write()
document.write("李郝帅");
运算符
1、算术运算符
- +加法
- -减法
- *乘法
- /除法
- %取余数、取模
2、比较运算符
-
> 大于
-
< 小于
-
== 是否相等 (不判断数据类型,如果字符串是数字,会转化成数字进行比较)
-
=== 权等(会判断数据类型,既要判断数值,也有判断类型)
-
>= 大于等于
-
<= 小于等于
-
!= 不等于
3、逻辑运算符
- 或 || (两边只要一边成立)
- 并且 && (两边都要成立)
4、赋值运算符
-
= 例子:a = 1
-
+= a+=1 相当于 a= a+1
-
-= a-=1 相当于a =a-1
-
= a=2 相当于 a= a2
-
/ = a/=2 相当于a=a/2
-
%= a%=2 相当于a=a%2
-
a++ 相当于a=a+1或者a+=1
-
a-- 相当于a=a-1
关于 + + i 和 i + + 的面试题
var i = 1;
alert(++i);
//i++;相当于 i+=1相当于i=i+1
++i;
alert(i++);
区别:
-
i + + 是先赋值在运算(如果打印,打印的是运算前的)
-
++ i 是先运算再赋值(如果打印,打印的是运算后的)
5、三元运算符、三目运算符
条件?条件成立代码:条件不成立代码
条件判断语句
if else条件语句
if(条件){//如果
条件成立执行的代码
}
else{
条件不成立执行的代码
}
if(条件1){//如果
条件1成立执行的代码
}
else if(条件2){
条件2成立执行的代码
}
else{
条件都不成立执行的代码
}
注意:if和else最多一个,else if可以多个或者没有
案例:一个按键让div显示隐藏
<style>
#div1 {
width: 100px;
height: 100px;
background: #000;
display: none;
}
</style>
<button id="btn1">按钮</button>
<div id="div1"></div>
var oBtn = document.getElementById("btn1");
var oDiv = document.getElementById("div1");
oBtn.onclick = function () {
if (oDiv.style.display == "block") {
oDiv.style.display = "none";
} else {
oDiv.style.display = "block";
}
};
switch条件语句
switch(表达式) {
case n:
代码块
break; //意思是终止下面的操作,跳出
case n:
代码块
break;
case n:
代码块
break;
default: //上面所有都不满足
默认代码块
}
解释:switch 可以理解为"开关、转换" case 可以理解为"案例、选项"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Djo7kYRU-1662618687466)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220828144746373.png)]
循环语句
for循环语句
for(初始值的声明;判断条件;自增或者自减){
条件成立执行代码
}
1.初始化声明
2.进行判断满不满足
3.满足,执行for里面的代码,不满足for循环结束
4.执行完代码,自增或者自减(因为要最终离开循环)
5.进行判断满不满足,依次执行3.4.5,直到条件不满足
for (var i = 0; i < 10; i = i + 1) {
console.log(i);
}
注意:循环几次,里面的代码执行几次
( break是直接终止 continue是单独中止一次 )
break:跳出整个循环
continue:跳出本次的循环
如果要跳出多层循环,添加一个空的,直接离开for循环
a:
for(var i=0;i<10;i++){
for(var j=0;j<3;j++){
if(i==2&&j==1){
break a;
}
console.log(i,j);
}
}
案例:一堆div点击变红
<style>
div {
width: 100px;
height: 100px;
background: black;
}
</style>
</head>
<body>
<div id="div1"></div>
<div></div>
<div></div>
<div></div>
<div></div>
var aDiv = document.getElementsByTagName("div");
// console.log(aDiv);
for (var i = 0; i < aDiv.length; i++) {
// console.log(i);
aDiv[i].onclick = function () {
// this 表示触发这个函数的东西 表示谁触发了这个函数
this.style.background = "red";
};
}
注意:
i++ 就是 i= i+1
这里是获取getElementsByTagName(" ") 一个数组
for循环里面的 i<a.Div.length 是遍历数组。
while循环
while(条件){
代码
自增或自减(不写就变成死循环)
}
var a = 0;
while (a < 3) {
console.log(a);
a++;
}
如果循环的是固定具体的次数,那么用for循环,如果不知道循环多少次,不是固定的次数,用while循环
do-while(只在面试题里面出来,基本不用)
do {
代码;
自增或者自减;
} while (条件);
var a = 0;
do {
console.log(a);
a++;
} while (a < 3);
while和do—while的区别在于,while如果第一次条件不成立,不会进入循环,do—while是先进入循环再判断,就算初始条件不满足,也换先执行一次。
数组
数组中的元素可以是任意的数据类型,也可以是对象,也可以是函数,也可以是数组。
创建数组对象
var wuzi=['大米','面','蔬菜','肉']
使用构造函数创建数组
var arr = new Array(参数);
区别:
new Array(只放一个数字) 不能创建出一个数组里面有一个数字,创建出一个长度为几的空数组
注意:数组是放数据的,里面可以放任意类型的数据,工作的时候一个数组类型基本相同
声明数组的方法
var arr=[1,2,3];
var arr2=new Array(1,2,3)
console.log(arr,arr2);
区别:
var arr=[3]; //生成一个 3数组
var arr2=new Array(3) //生成三个 空数组
console.log(arr,arr2);
数组的索引
索引 (下标) :用来访问数组元素的序号,代表的是数组中的元素在数组中的位置(下标从 0 开始算起)。
获取数组中的元素
数组[索引];
var arr = [21, 22, 23];
console.log(arr[0]); // 打印结果:21
console.log(arr[5]); // 打印结果:undefined
向数组中添加元素
数组[索引] = 值;
// 向数组中添加元素
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[5] = 50;
获取数组的长度
可以使用length
属性来获取数组的长度(即“元素的个数”)。
数组的长度是元素个数,不要跟索引号混淆。
数组的长度 = 数组名.length;
var arr = [21, 22, 23];
console.log(arr.length); // 打印结果:3
遍历数组
遍历: 就是把数组中的每个元素从头到尾都访问一次。
最简单的做法是通过 for 循环,遍历数组中的每一项。
var arr = [10, 20, 30, 40, 50];
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]); // 打印出数组中的每一项
}
数组的一系列操作
var aaa = ["刘帅", "帅二娃", "帅先生", "250"];
// 前面 增加
aaa.unshift("我儿子");
//后面增加
aaa.push("我的好大儿");
//删除前面的
aaa.shift();
//删除最后面的
aaa.pop();
//删除指定位置 splice.() 起始位置,删除几个,添加内容
aaa.splice(1, 1);
// 添加内容
aaa[1] = "添加的刘帅";
console.log(aaa);
// 两个数组合并到一个数组 原数组不会发生变化
var arr = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = arr.concat(arr2);
console.log(arr3, arr, arr2);
// 把数组变成字符串
var str = arr3.join(); //括号里面写连接的方式 原数组不会发生变化
console.log(str);
alert(typeof str);
// 数组翻转 原数组会发生变化
var newArr = arr3.reverse();
console.log(newArr, arr3);
//如何清空一个数组
arr.length = 0;
arr2 = [];
arr3.splice(0, arr3.length);
console.log(arr, arr2, arr3);
//排序
var arr4 = [3, 5, 1, 8, 9, 2, 6];
arr4.sort(); //默认按照字典顺序排列
console.log(arr4);
var arr5 = ["a", "aa", "ba", "ac", "da", "db"];
arr5.sort();
console.log(arr5);
//按照大小顺序排
var arr6 = [3, 5, 1, 8, 9, 2, 6, 12, 15, 23];
arr6.sort(function (a, b) {
//告诉系统,以什么样的规则去排序
//a,b 就是数组中的每一项
return a - b; //传过去一个比较的规则 规则就是让两个数字,比较大小
// a-b 升序:从小到大排 b-a 降序:从大到小排
});
console.log(arr6);
冒泡排序
var arr = [20, 10, 50, 30, 40];
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
数组的方法清单
数组的类型相关
方法 | 描述 |
---|---|
Array.isArray() | 判断是否为数组 |
toString() | 将数组转换为字符串 |
Array.from(arrayLike) | 将伪数组转化为真数组 |
数组元素的添加和删除
方法 | 描述 | 备注 |
---|---|---|
push() | 向数组的最后面插入一个或多个元素,返回结果为新数组的长度 | 会改变原数组 |
pop() | 删除数组中的最后一个元素,返回结果为被删除的元素 | 会改变原数组 |
unshift() | 在数组最前面插入一个或多个元素,返回结果为新数组的长度 | 会改变原数组 |
shift() | 删除数组中的第一个元素,返回结果为被删除的元素 | 会改变原数组 |
slice() | 从数组中提取指定的一个或多个元素,返回结果为新的数组 | 不会改变原数组 |
splice() | 从数组中删除指定的一个或多个元素,返回结果为被删除元素组成的新数组 | 会改变原数组 |
fill() | 填充数组:用固定的值填充数组,返回结果为新的数组 | 会改变原数组 |
数组的合并和拆分
方法 | 描述 | 备注 |
---|---|---|
concat() | 合并数组:连接两个或多个数组,返回结果为新的数组 | 不会改变原数组 |
join() | 将数组转换为字符串,返回结果为转换后的字符串 | 不会改变原数组 |
split() | 将字符串按照指定的分隔符,组装为数组 | 不会改变原字符串 |
注意,split()是字符串的方法,不是数组的方法。
数组排序
方法 | 描述 | 备注 |
---|---|---|
reverse() | 反转数组,返回结果为反转后的数组 | 会改变原数组 |
sort() | 对数组的元素,默认按照Unicode 编码,从小到大进行排序 | 会改变原数组 |
遍历数组
方法 | 描述 | 备注 |
---|---|---|
for 循环 | 这个大家都懂 | |
map() | 对原数组中的每一项进行加工,将组成新的数组 | 不会改变原数组 |
filter() | 过滤数组:返回结果是 true 的项,将组成新的数组,返回结果为新的数组 | 不会改变原数组 |
查找数组里包含某个东西
indexOf es5 includes es6
数组变成字符串
join() 直接把数组直接转成字符串 是带逗号的 原数组没有发生变化
join(‘’) 数组的所有内容拼接在一起
join(‘T’) 拼接的时候中间加拼接内容
循环方法
for
let arr = [1, 2, 3, 4, 5];
for(let i=0;i<arr.length;i++){
}
forEach循环
//forEach 循环数组里面的每一个东西
//里面放一个函数 函数里面,系统会传过来两个参数
第一个参数是循环过程中,数组的每一项,第二个参数是,循环过程中,每一项的下标
不会返回一个新的数组, 就是单纯的循环
let arr = [1, 2, 3, 4, 5];
var arr1=['hello','hei','apple','banana']
let res = [];
for (let i = 0; i < arr1.length; i++) {
res.push(arr1[i].toUpperCase());
}
console.log('res', res);
map 循环数组
//循环数组里面的每一个东西
//map里面放一个函数 函数里面,系统会传过来两个参数
//第一个参数是循环过程中,数组的每一项,第二个参数是,循环过程中,每一项的下标
//map的返回值是一个新的数组。新的数组中的每一项都需要在函数中return
let mapArr = arr1.map((v, i) => {
return v.toUpperCase();
})
console.log(mapArr);
filter循环数组
//循环数组里面的每一个东西
//里面放一个函数 函数里面,系统会传过来两个参数
//第一个参数是循环过程中,数组的每一项,第二个参数是,循环过程中,每一项的下标
//filter的返回值是一个新的数组,新数组的每一项都需要在函数中return,必须符合条件
//需要return 一个条件
let filterArr = arr1.filter((v, i) => {
console.log(v, i)
return v.includes('a')
})
console.log(filterArr);
函数
什么是函数?
就是将一些功能或语句进行封装,在需要的时候,通过调用的形式,执行这些语句。
-
函数也是一个对象
-
使用
typeof
检查一个函数对象时,会返回function -
可以包裹一堆代码的容器
好处:
- 把某一些功能可以整个到一个函数中。 random() findInArr()
- 重复利用
- 利于开发配合
函数的定义/声明
函数怎么定义
命名函数:使用函数声明来创建一个函数(也就是 function 关键字)什么时候调用,什么时候执行函数里面的代码
function 函数名([形参1,形参2...形参N]){
// 备注:语法中的中括号,表示“可选”
语句 代码...
}
函数名() 函数的调用
let 函数名=function(){ 把一个匿名函数赋值给一个变量
//code
}
函数名() 函数的调用
区别:下面这个方式必须先定义在使用,因为变量会提升
匿名函数:因为没有名字需要依靠别的东西
oBtn.onlick =function(){}
window.οnlοad=function(){}
事件 document.οnclick=function(){}
定时器 setTimeout(function(){},1000)
对象的方法 let json={ fn:function(){ } } json.fn();
事件触发的时候执行
fn( ) 和 fn 的区别【重要】
-
fn()
:调用函数。调用之后,还获取了函数的返回值。 -
fn
:函数对象。相当于直接获取了整个函数对象。
特殊的匿名函数:自执行匿名函数
两个括号一个分号,第一个括号里面加function(){}
(function 形参() {
代码
})
(传参);
自执行匿名函数的好处
可以解决变量冲突的问题。第三方的插件都会用自治性匿名函数包裹。第三放插件的变量就变成局部变量。。。 现在可以用{}代替自治性匿名函数,但是不能完全代替 不能传参
! - + ~ 这几个标志表示为自执行函数
!function(){
//code
}()
es6里面对函数新加了一些东西
默认参数
function 函数名(参数=默认值){
}
//如果这个参数不传,就是默认值。
三个点运算符 | reset运算符 | 剩余参数运算符 …
1、把一个数据集合拆开
- 复制一个数组、json/创建一个数组、json
- 合并多个数组或者json
- 把非(伪)数组转化成数组
什么是伪数组:只有下标和长度,没有数组的方法
2、可以把一些东西合并起来当成数组或者json
- 解构赋值中剩余的合并
- 不用argument了 直接用剩余参数
函数的调用
//函数怎么使用
函数名() 函数的调用
//什么时候后调用,什么时候执行函数里面的代码
普通函数的调用
function fn1() {
console.log("我是函数体里面的内容");
}
fn1(); // 调用函数
绑定事件函数的调用
var btn = document.getElementById('btn');
//2.绑定事件
btn.onclick = function() {
console.log('点击按钮后,要做的事情');
};
函数的参数:形参和实参
形参:
- 概念:形式上的参数。定义函数时传递的参数,当时并不知道是什么值。
- 定义函数时,可以在函数的
()
中来指定一个或多个形参。 - 多个形参之间使用
,
隔开,声明形参就相当于在函数内部声明了对应的变量,但是并不赋值。
实参:
- 概念:实际上的参数。调用函数时传递的参数,实参将会传递给函数中对应的形参。
- 在调用函数时,可以在函数的
()
中指定实参。
注意:实际参数和形式参数的个数,一般要相同。
js中函数传参时如果传递多个参数,需要用",",隔开,而且需要不同的变量去接收参数,传递的参数与接收参数的变量是一一对应的
实参的数量(实参和形参的个数不匹配时)
调用函数时,解析器也不会检查实参的数量。
-
如果实参的数量多余形参的数量,多余实参不会被赋值。
-
如果实参的数量少于形参的数量,多余的形参会被定义为 undefined。表达式的运行结果为 NaN。
function sum(a, b) { console.log(a + b); } sum(1, 2); // 3 sum(1, 2, 3); // 3 sum(1); //NaN
arguments :实参的参数集合,里面装了所有实参
操作arguments[ ]
当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。
在 JavaScript 中,arguments 实际上是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象(只有函数才有 arguments 对象),arguments 对象中存储了传递的所有实参.
arguments的展示形式是一个伪数组。伪数组具有以下特点:
- 可以进行遍历;具有数组的 length 属性。
- 按索引方式存储数据。
- 不具有数组的 push()、pop() 等方法。
函数的返回值
console.log(sum(3, 4)); // 将函数的返回值打印出来
//函数:求和
function sum(a, b) {
return a + b;
}
return 的作用是结束方法(终止函数)。
注意:
- return 的值将会作为函数的执行结果返回,可以定义一个变量,来接收该结果。
- 在函数中return后的语句都不会执行(函数在执行完 return 语句之后停止并立即退出函数)
- 如果return语句后不跟任何值,就相当于返回一个undefined
- 如果函数中不写return,则也会返回undefined
- 返回值可以是任意的数据类型,可以是对象,也可以是函数。
- return 只能返回一个值。如果用逗号隔开多个值,则以最后一个为准。
箭头函数
箭头函数目的是为了简化写法,和优化this指向
普通函数
const fn=function(){}
箭头函数
const fn=()=>{}
箭头函数的简写
const fn=a=>{} //只有一个参数的时候()可以写
const fn=(a,b)=>a+b //只有一句return的时候 {}和return都可以不写
箭头函数的this指向:与该函数所在的父级函数内的this指向相同
箭头函数和普通函数的区别
-
-
- 箭头函数没有arguments 用…代替
- 箭头函数不能作为构造函数,也就是不能new
- 箭头函数不能作为generator函数 暂时不用管
-
字符串
关于字符串
只要es6 es5 html5就不兼容ie低版本
var 变量=‘ ’
var 变量=“ ”
var 变量=
(反撇 tab上面那个键,支持换行)
- 放变量方便 ${ }
- 好看
操作字符串方法
查找字符串
indexOf(‘要查询的字符串’)
-
返回的是字符串所在的位置下标
-
从左往右查找,找到后返回,不会往下找了
-
没找到返回-1
str.lastIndexOf(‘要查询的字符串’)
- 从右往左查找,找到后返回,不会往下找了
var str = "hello world(你好)";
var index = str.indexOf("e");
var index = str.indexOf("ll");
var index = str.indexOf("z"); //查不到了就是-1
var index = str.indexOf("o"); //两个相同的的,只查询第一个
console.log(index);
截取字符串
str.substring(开始位置,结束位置)
- 不包括后面
- 结束位置可以不写,如果不写默认截取到最后
var str = "hello world(你好)";
var a = str.substring(0, 2);
console.log(a); //he 左闭右开
把字符串变成数组
str.split(); //把整个字符串放进一个数组
str.split(‘’); //把所有字符串都切割放进一个数组
str.split(‘某种方式切割’)
返回一个数组
var str = "hello world(你好)";
var b = str.split();
console.log(b);
var c = str.split("");
console.log(c);
大小写转化
toLowerCase()转小写
toUpperCase ( ) 转大写
var str = "hEllo world(你好)";
var d = str.toLowerCase();
var e = str.toUpperCase();
console.log(e);
通过下标返回对应的字符串
str.charAt(下标) 返回对应的字符串
var str = "hEllo world(你好)";
var f = str.charAt(0);
console.log(f); //h
字符串 ‘hello world’ 如果遇到了字符串拼接 ‘hello ‘+变量+’ world’
里面的东西太多的时候直接换行不能用
在es6里面出来了一个新的写法 hello ${变量} world
里面随便换行
简单的字符串可以用’ ’ 需要复杂的换行、或者里面拼接变量用``
案例:让首字母大写
'hello world' -> 'HelloWorld'
var str = "hello world"; //每个首字母大写
function toUp(str) {
var arr = str.split(" "); //通过空格,切割成一个数组
for (var i = 0; i < arr.length; i++) {
//循环每一项
//重新改数组
//arr[i]的这一项的首字母大写+这一项除首字母的东西
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
}
return arr.join(""); //把转换后的数组,拼接成字符串返回
}
aaa = toUp(str);
console.log(aaa);
截取文件名后缀 ‘a.txt’--> txt 'a.a.a.png' --> png
function fn(str) {
return str.substring(str.lastIndexOf(".") + 1); 先从左往右查询坐标,获取坐标后进行分割
}
console.log(fn("a.txt"));
console.log(fn("a.a.a.a.png"));
字符串的方法
查找字符串所在的位置
-
indexOf(‘要查找的字符串’) 返回下标,没有找到返回-1
-
lastIndexOf(‘要查找的字符串’) 返回下标,没有找到返回-1
通过下标找对应的字符串
-
charAt(‘下标’) 返回的是字符串,没有内容返回空字符串。
-
str[ 下 标 ] 不兼容IE低版本
大小写转化
-
toLowerCase()
-
toUpperCase()
截取字符串
slice(?开始下标,?结束下标)
解释:从字符串中截取指定的内容。不会修改原字符串,而是将截取到的内容返回。
注意:上面的参数,包左不包右。参数举例如下:
(2, 5)
截取时,包左不包右。(2)
表示从指定的索引位置开始,截取到最后。(-3)
表示从倒数第三个开始,截取到最后。(1, -1)
表示从第一个截取到倒数第一个。
substring(开始下标,?结束下标) ?是可有可无的意思
解释:从字符串中截取指定的内容。和slice()
类似。
substring()
和slice()
是类似的。但不同之处在于:
substring()
不能接受负值作为参数。如果传递了一个负值,则默认使用 0。substring()
还会自动调整参数的位置,如果第二个参数小于第一个,则自动交换。比如说,substring(1, 0)
相当于截取的是第一个字符。
如果开头是负数:
substring 当做0开头
slice 找不到
如果结尾数字比开始数字小:
substring 相当于把开始结束反过来
slice 找不到
如果结束是负数:
substring 当做0处理
slice 从后往前取
开始结束都是负数:都为空
把字符串变成数组
str.split(‘某种方式切割’); 把整个字符串放进一个数组
返回一个数组
是否包含某个字符串
includes() 返回的是true和false
是不是以什么开头
startsWith() 返回的是true和false es6
是不是以什么结尾
endWith() 返回的是true和false es6
最大长度,如果不够长用什么补
padStart ( ) es6
padEnd( ) 在结尾填充字符串
trim( ) 去除首尾空格 es5
trimStart() 去除首空格 es6
trimEnd() 去除结尾空格 es6
search(正则) 搜索 返回的下标
match(正则) 查找一个或多个字符串,返回的数组
replace(’要替换的字符串‘,’新的字符串‘)
replace(正则,“新的字符串”)
replace(正则,function(v){ return 新的字符串})
ES6字符串的新增方法
模板字符串 `` aaa${变量}bbb
includes(‘字符串’) 字符串内是否包含某个字符串
startWith(‘字符串’) 字符串的开头是否包含某个字符串
endWith(‘字符串’) 字符串的结尾是否包含某个字符串
padStart(最小位数,‘要补的字符串’) 开头补
padEnd(最小位数,‘要补的字符串’) 最后补
trimStart() 开头去空格
trimEnd() 结尾去空格
repeat(次数) 重复
正则表达式
- 用来操作字符串的
有一些字符串的操作用常规的字符串方法操作非常复杂,用正则方便
- 一定规律的字符串
全称叫做正则表达式 regular expression 也叫规则表达式
- 可以用来描述一套规则
他是一种独立语言,很多语言都会引入
怎么创建一个正则
正则也是一个对象
var reg = /规则 /选项修饰符 字面量的创建
var reg = new RegExp(‘ ’) 通过new来创建
选项修饰符
- i ignore 忽略大小写
- g global 全局
- m mutil-line 多行
可以同时使用,没有先后顺序
转义字符 用+字母代表特定的规则
\ 转义
\s space 空格
\d 数字
\D 非数字
\w 单词
\W 非单词
. 代表任何任意
如果想代表本身 .
所有有特殊含义的,想要用本身的含义都需要\转义 \本身
量词
{ 最小值,?最大值} 最大值可以不写
{n} 正好n个 eg :/1{2}/ 11
{n,m} 最少n个,最多m个 ,m包含
eg: /1{1,3}/ 1 11 111
{n,} 最少n个,多了不限
几个特殊写法的量词
{1,} 最少1个,多了不限 +代替
{0,} 可以没有,有了不上限 *代替
{0,1} 可以没有,有只有1个 ?代替
特殊符号
| 或 [ab] a|b a或b
^ 行首
$ 行尾
[ ]
1 .或
[abc] 代表 a|b|c
[a|b] 代表 a|b或者是|
2.区间
[a-z] 代表 所有的字母
[0-9] 代表 所有的数字,相当于\d
3.排除
[^]排除所有的可能
[^0-9] 除了数字所有都可以
()提高优先级 分组
特殊题:
[1-38] 1|2|3|8
[1-3-8] 1|2|3|-|8
[\u4e00-\u9fa5] 汉字
/^1[3-9]\d{9}&/ qq号校验 第一位为1,后面的数字3-9,九位
正则两种声明方式的区别
1.通过new来写的 转义符需要转两次 (字符串里面两个\才有转义的作用)
2.new里面可以放变量 用处不大
时间对象
内置对象 Date 用来处理日期和时间。拿到这个对象就可以拿到当前系统时间
创建Date对象有两种写法:
- 写法一:如果Date()不写参数,就返回当前时间对象
- 写法二:如果Date()里面写参数,就返回括号里输入的时间对象
写法一:不传递参数时,则获取系统的当前时间对象
var date1 = new Date();
console.log(date1);
console.log(typeof date1);
法二:传递参数
var date11 = new Date('2022/02/17 21:00:00');
console.log(date11); // Mon Feb 17 2022 21:00:00 GMT+0800 (中国标准时间)
var date21 = new Date(2020, 2, 18); // 注意,第二个参数返回的是三月,不是二月
console.log(date21); // Wed Mar 18 2020 00:00:00 GMT+0800 (中国标准时间)
Date对象的方法
Date对象 有如下方法,可以获取日期和时间的指定部分:
方法名 | 含义 | 备注 |
---|---|---|
getFullYear() | 获取年份 | |
getMonth() | 获取月: 0-11 | 0代表一月 |
getDate() | 获取日:1-31 | 获取的是几号 |
getDay() | 获取星期:0-6 | 0代表周日,1代表周一 |
getHours() | 获取小时:0-23 | |
getMinutes() | 获取分钟:0-59 | |
getSeconds() | 获取秒:0-59 | |
getMilliseconds() | 获取毫秒 | 1s = 1000ms |
先要获取系统的时间对象-当前时间下的时间对象
var oDate=new Date():
获取年份
var y = oDate.getFullYear();
获取月份 从0开始 0-11
var x = oDate.getMonth();
获取的日
var a = oDate.getDate();
获取小时
var h = oDate.getHours();
获取分钟
var m = oDate.getMinutes();
获取秒
var s = oDate.getSeconds();
获取的星期 0-6 0是星期天 1-6是周一到周六
var b = oDate.getDay();
获取时间戳
时间戳的定义和作用
时间戳:指的是从格林威治标准时间的1970年1月1日,0时0分0秒到当前日期所花费的毫秒数(1秒 = 1000毫秒)。
计算机底层在保存时间时,使用的都是时间戳。时间戳的存在,就是为了统一时间的单位。
getTime():获取时间戳
getTime()
获取日期对象的时间戳(单位:毫秒)。这个方法在实战开发中,用得比较多。但还有比它更常用的写法,我们往下看。
获取 Date 对象的时间戳
获取 Date 对象的时间戳(较常用的写法)
var time2 = new Date().getTime();
console.log(time2); // 打印结果举例:1589448165370
获取当前时间的时间戳
获取当前时间的时间戳,除了上面的几种方式之外,还有另一种方式。代码如下:
获取当前时间的时间戳(很常用的写法)
var t =Date.now()
console.log(Date.now()); // 打印结果举例:1589448165370
获取时间戳 从1970年1月1日到现在的毫秒数
var t = oDate.getTime();
除了这种方法获取时间戳还有一种方法
var t =Date.now()
直接出来年月日的时间
var time1 = oDate.toLocaleDateString();
console.log(time1);
直接出来年月日的时间 小时分钟秒
var time2 = oDate.toLocaleString();
console.log(time2);
小时分钟秒
var time3 = oDate.toLocaleTimeString();
console.log(time3);
设置时间
var oDate = new Date();
oDate.setFullYear(1999);
oDate.setMonth(11);
oDate.setDate(1);
简写的设置
可以设置年,月,日
oDate.setFullYear(1999, 11, 1);
小时也可以设置小时,分钟,秒
oDate.setHours(11, 12, 13);
2022年8月1日14点23分4秒
var oDate = new Date(2022, 8, 1, 14, 23, 54);
var oDate = new Date("2022-02-02");
var oDate = new Date("2022/02/23 14:29:54")
案例:距离国庆还有多少天
var nowDate = new Date(); //现在的时间对象
var futureDate = new Date("2022/10/1 0:0:0"); //未来的时间对象
var total = futureDate.getTime() - nowDate.getTime(); //现在距离国庆的毫秒数=国庆距离1970,1,1的毫秒数-现在距离1970,1,1的毫秒数
console.log(total);
//天
var day = Math.floor(total / 1000 / 60 / 60 / 24); //一天有86400秒
//小时
var hour = Math.floor((total / 1000 / 60 / 60) % 24);
//分钟
var minutes = Math.floor((total / 1000 / 60) % 60);
//秒
var sec = Math.floor((total / 1000) % 60);
console.log(day, hour, minutes, sec);
DOM 文档对象模型
文档是如何构建的
DOM树 文档是以DOM树的方式构建的
节点、根节点、父节点、子节点、兄弟节点
分支
根
对html来说最大的根节点是document,文本(文档)
节点的类型
- 根节点 document
- 元素节点 div p span
- 文本节点 内容
- 属性节点
用的最多的是根节点和元素节点
关于节点有一些特殊的东西
nodeName 节点的名字
元素节点 nodeName就是节点名称大写标签名、
属性节点 nodeName和属性名相同
文本节点 nodeName 始终是#text
nodeValue 节点的值
元素节点 null
属性节点 属性值
文本节点 文本本身
nodeType 节点的类型
元素节点 1
属性节点 2
文本节点 3
节点的获取
通过id获取
document.getElenmentById(‘id名字’)
通过标签名获取
document.getElenmentByTagName(‘标签名’)
通过class名获取
document.getElenmentByClassName(‘class名’) 是es5出来的,不兼容ie低版本
通过选择器获取
document.querySelector(‘选择器(#div p a)’) 获取的是一个
document.querySelectorAll(‘选择器’) 获取的是一组 不兼容ie低版本**
如何获取子节点
childNodes 获取出来的是所有类型的节点,平常不用
children 获取所有的元素节点(第一层的所有元素节点)
如何获取父节点
parentNode
获取兄弟节点
上一个兄弟节点
previousElementSibling 不兼容IE低版本
下一个兄弟节点
nextElementSibling 不兼容IE低版本
获取第一个子节点
firstElementChild 不兼容IE低版本
获取最后一个子节点
lastElementChild 不兼容IE低版本
创造一个节点
document.createElement(‘标签名’)
必须是document创建
必须插入或者放在body的某个地方才有用
var bbb = document.querySelector("#div2");
var aaa = document.createElement("i");
var oSpan = document.querySelector("#div2 span");
bbb.insertBefore(aaa, oSpan);
var oDiv=document.querySelector('#div1');
var oDiv2=document.querySelector('#div2');
oDiv.innerHTML='<i>我是斜体</i>'
/*
创建一个元素插入
*/
var oP=document.createElement('p');
var oB=document.createElement('b');
添加一个节点
innerHTML = ‘节点’ ,这种添加相当于是覆盖
父节点.appendChild(子节点) 向父亲的最后追加一个节点
父节点.appendChild(新的子节点); 父节点的最后插入一个新的子节点。
var bbb = document.querySelector("#div2");
var aaa = document.createElement("i");
bbb.appendChild(aaa);
console.log(bbb);
父节点.insertBefore(‘把谁插入到谁的前面’)
<div id="div1">
<p>111</p>
<p>222</p>
<p class="p1">333</p>
<p>444</p>
<p>555</p>
</div>
<div id="div2">
<span>哈哈</span>
</div>
父节点.insertBefore(新的子节点,作为参考的子节点)
var oSpan = document.querySelector("#div2 span");
var bbb = document.querySelector("#div2");
var aaa = document.createElement("i");
bbb.insertBefore(aaa, oSpan);
console.log(bbb);
删除一个节点
父节点.removeChild(子节点)
不能删除一组节点
<div id="div1">
<p>111</p>
<p>222</p>
<p class="p1">333</p>
<p>444</p>
<p>555</p>
</div>
<div id="div2">
<span>哈哈</span>
</div>
var oSpan = document.querySelector("#div2 span");
var bbb = document.querySelector("#div2");
var aaa = document.createElement("i")
bbb.removeChild(oSpan);
替换一个节点
父节点.replaceChild(替换的元素【新】,被替换的元素【旧】)
<div id="div1">
<p>111</p>
<p>222</p>
<p class="p1">333</p>
<p>444</p>
<p>555</p>
</div>
<div id="div2">
<span>哈哈</span>
</div>
var oSpan = document.querySelector("#div2 span");
var bbb = document.querySelector("#div2");
var ccc = document.createElement("b");
bbb.replaceChild(ccc, oSpan);
克隆一个节点
.cloneNode() 只克隆当前元素
.cloneNode(true) //所有的都克隆过来
var oDiv = document.querySelector("#div1");
var oBox = document.querySelector("#box");
var newDiv = oDiv.cloneNode();
oBox.appendChild(newDiv);
oDiv.cloneNode(true);
克隆过后需要记住把他们加进去
对节点的内容的操作
- innerHTML 解析、获取html内容
- innerText 操作的是文本内容,不能获取解析html内容
- outerHTML 操作文本+标签+自身标签
对节点属性的操作
. [ ]
平时用的最多,但是不能获取到自定义属性,除非是js后面添加的
对于非法的自定义属性,浏览器在解析html的时候会过滤
js自己添加的属性能够通过 . [ ]获取
<div title="aaa"></div>
var oDiv = document.querySelector("div");
oDiv.title = 111;
oDiv["title"] = 222;
getAttribute(‘属性名’)
setAttribute(‘属性名’,‘属性值’)
removeAttribute(‘属性名’)
不管你是不是自定义,都能操作
var oDiv = document.querySelector("div");
oDiv.setAttribute("aaa", "111");
oDiv.removeAttribute("title", "123");
console.log(oDiv);
在htm5之前,行业有个约定俗成的规矩,自定义属性加一个前缀 data-xxx
html5出来以后,把data-xx变成了规范
获取: 元素.dataset.属性名
设置 : 元素.dataset.属性名='属性值’
var oDiv = document.querySelector("div");
oDiv.dataset.aaa = 2;
console.log(oDiv.dataset);
总结:
平时,系统自带的用. [ ] 毕竟写起来方便
如果是自定义的用data-xxx
Attribute一般不用,在设计框架的时候用
对class的操作
.className = ‘xxx’
对class重新赋值
h5出来了新功能
.classList.add(“class名”);
.classList.remove(“class名”)
对样式的操作
获取:元素.style.样式名
设置:元素.style.样式名=‘样式值’
行间样式的设置
getComputedStyle(元素).样式 :获取样式 计算过后的样式 兼容高级浏览器
注意:获取出来的是加单位的字符串
注意:颜色 不管用的什么表示法获取出来的都是rgb
拓展
str.indexOf找不到为什么返回-1,不返回null undefined
函数封装的时候约定返回值最好是同一种数据类型
定义一个变量,如果刚开始赋值的时候最后赋同类型的
var oDiv = null
DOM里面特殊的对象
document 根元素
html : document.docunmentElement 相当于html
body : document.body 相当于body
事件
-
什么是事件?
用户的操作交互
onclick: 当用户点击的时候
onmouseover:当鼠标移入的时候
onmouseout:当鼠标移出的时候
alert(‘弹框内容’) 弹框
-
事件加给谁?
要操作谁就加给谁。
-
事件什么元素都可以添加事件吗?
理论上所有标签都可以加事件,但是平常给body以及body里面的标签加事件
事件的分类
鼠标事件
onclick 一次点击,相当于,一次鼠标按下 + 一次鼠标抬起
ondblclick 双击
onmouseover 鼠标移入
onmouseout 鼠标移出
onmousemove 鼠标移动的时候
onmouseenter 鼠标进入
onmouseleave 鼠标离开
- 没有事件冒泡的行为
- 不兼容低级浏览器
高频触发事件,这种事件不要写复杂的逻辑,后期这种事件也要做性能优化
onmousedown 鼠标按下去
onmouseup 鼠标抬起
oncontextmenu 点击鼠标右键
键盘事件
onKeydown 键盘按下
onKeyup 键盘抬起
键码
a 65 空格 32 数字1 49 回车 13 左 37 上 38 右 39 下 40
js里不能同时出现两个键码
在事件对象中得组合键: ctrlKey altKey shiftKey
ui事件、窗口事件
onload
onscroll
onresize window.onresize 当窗口大小发生变化的时候
输入事件
oninput 只兼容高级浏览器
焦点事件
onfocus 当获取焦点的时候
onblur 当失去焦点的时候
元素.focus
元素.blur
change事件
用于select 、input:file
当select没有value的时候。默认获取文本值,有value获取value
文件上传,获取元素里面的file属性
不能用在input、texttarea里面,用在里面会出现,失去焦点才触发的情况
ui事件、窗口事件
onload
onscroll
onresize window.onresize 当窗口大小发生变化的时候
事件(JavaScript)的添加方式
1、行间的事件添加方式 在标签上以属性的方式
<script>
function fn(){}
</script>
<div onclick="fn()"></div>
2、操作属性的方式获取 可以获取所有要用的元素、标签 > 进行添加
同一个元素不能加多个相同的事件
解除: oBtn.οnclick=null
window.onload = function(){
//窗口加载完,执行函数
var oBbt = document.getElenmentById('btn');
var oDiv = document.getElenmentById('div1');
oBtn.onclick=function(){
oDiv.style.display='none'
}
}
案例:让div盒子显现出来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
width: 100px;
height: 100px;
background: red;
display: none;
}
</style>
</head>
<body>
<!-- <button οnclick="让div样式里面的display变成block">显示</button> -->
<!-- <button οnclick="div1.style.display='block'">显示</button>
<div id="div1"></div> -->
<!--
div1.style.display='block'
不是标准的写法。不被协议组织认可的写法
-->
<button onclick="document.getElementById('div1').style.display='block'">显示</button>
<div id="div1"></div>
</body>
</html>
3、元素.addEventListener( 不加on的事件,事件触发执行函数函数名不加(),是否事件下沉)
目的:给同一个元素加多个相同的事件
第三个参数true是事件下沉,false是事件冒泡,默认是false
解除事件 :元素.removeEventListener(‘不加on的事件名’,事件触发时候执行的函数,是否事件捕获)
4、事件委托
把事件的添加委托给父级元素,或者在往上的元素.
ul.onclick = function(e) {
if (e.target.tagName == "BUTTON") {
e.target.parentNode.remove();
}
事件委托的原理
利用事件冒泡,把事件冒泡给父元素。通过事件对象里面的target找到触发的原对象
为什么要委托
1、提高性能 给多个相同元素加相同事件的时候,平常用for,为了提高性能可以用事件委托
2、为不存在的,未来的元素加事件
事件对象
事件触发时候,包含事件详细信息的对象。
函数触发的时候里面有个东西 event
event 不兼容低版本火狐。现在全部兼容
clientX/clientY 可视区的坐标
pageX/pageY 页面的距离坐标 兼容高级浏览器
cancelBubble 阻止事件冒泡
target 触发事件的目标元素
event.preventDefault() 阻止浏览器默认行为
- 右键菜单
- form表单的提交
- 阻止浏览器选中
- 阻止出现禁止标志
事件流
当事件发生的时候,会有一个执行的顺序,这个执行的顺序,就叫做事件流(事件的流向)
事件冒泡
从当前触发的元素开始执行,一层一层向父级递进,在这个过程中,有相同的事件,触发,没有相同的事件继续向上递进,直到document (ie公司提出)
事件下沉(事件捕获)
当事件触发,最先从document开始,一层一层向下执行,直到执行触发事件的元素,有相同的事件触发,没相同元素继续(网景公司提出)
默认都是事件冒泡
阻止冒泡: cancelBubble =true
event.cancelBubble =true
案件:鼠标拖拽
<style>
div {
width: 100px;
height: 100px;
background: #2f90ff;
position: absolute;
top: 0;
left: 0;
}
</style>
<body>
<div></div>
</body>
// script
var oDiv = document.querySelector("div");
var disX;
var disY;
function down() {
disX = event.pageX - oDiv.offsetLeft;
disY = event.pageY - oDiv.offsetTop;
document.addEventListener("mousemove", moveFn);
document.addEventListener("mouseup", upFn);
//阻止浏览器的事件发生
event.preventDefault();
}
function moveFn() {
var left = event.pageX - disX;
var top = event.pageY - disY;
//限制范围
if (left <= 0) {
left = 0;
} else if (
left >=
document.documentElement.clientWidth - oDiv.offsetWidth
) {
left = document.documentElement.clientWidth - oDiv.offsetWidths;
}
if (top <= 0) {
top = 0;
} else if (
top >=
document.documentElement.clientHeight - oDiv.offsetHeight
) {
top = document.documentElement.clientHeight - oDiv.offsetHeight;
}
oDiv.style.left = left + "px";
oDiv.style.top = top + "px";
}
function upFn() {
document.removeEventListener("mousemove", moveFn);
}
oDiv.addEventListener("mousedown", down);
如何获取元素
通过id名来获取元素 document.getElementById(‘id名’)
通过标签获取元素 document.getElementsByTagName(" ") 一个数组
注意:通过标签获取的是集合元素(一组元素),要取到其中某一个,需要用到下标
它还有拥有length 长度
不仅可以在document下获取,也可以在其他父级下获取(见下拉列表案例)
哪怕获取出来的是一个也是一组
案件:下拉列表选择
<style>
* {
margin: 0;
padding: 0;
}
div {
margin: 30px 40px;
}
li {
list-style: none;
height: 26px;
line-height: 26px;
border-bottom: 1px solid #ddd;
text-align: center;
}
li:hover {
background: #56c0ff;
color: white;
}
h4 {
width: 80px;
height: 30px;
border: 1px solid black;
text-align: center;
line-height: 30px;
text-indent: 4px;
}
ul {
border: 1px solid #eee;
width: 80px;
display: none;
}
</style>
<div>
<h4>html</h4>
<ul>
<li>html</li>
<li>css</li>
<li>js</li>
<li>node</li>
</ul>
</div>
var oH4 = document.getElementsByTagName("h4")[0];
var oUl = document.getElementsByTagName("ul")[0];
var aLi = oUl.getElementsByTagName("li");
oH4.onclick = function () {
oUl.style.display = "block";
};
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = function () {
oUl.style.display = "none";
oH4.innerHTML = aLi[i].innerHTML;
};
}
js的样式操作
获取样式 元素.style.xxx
修改样式 元素.style.xxx=‘xxx’
注意:如果操作的是带连字符-怎么办, background-color backgroundColor
还可以通过修改class属性,达到修改样式的目的
也可以通过修改link标签的href,达到修改样式的目的
虽然修改样式多种方法,但是不要混着用,容易出现权重的问题
js文本操作
获取文本 元素.innerHTML
修改文本(文本赋值) 元素.innerHTML=‘xxx’
js属性操作
获取属性的值:元素.属性
修改属性的值:元素.属性=‘xxxx’ className=‘xxx’
● 注意:如果要操作class 需要写className
数学方法
随机数:Math.random(); 0-1 不包含1
//0-1之间的随机数
var a=Math.random();
console.log(a);
//想得到一个0-10之间的随机数怎么办 整数
parseInt(Math.random()*10+0);
//想要0-8之间的数
parseInt(Math.random()*8+0);
//10到20之间的数
parseInt(Math.random()*10+10)
//5-12之间的数
parseInt(Math.random()*7+5)
// n-m之间的数
parseInt(Math.random()*(m-n)+n)
function random(n,m){
return parseInt(Math.random()*(m-n)+n)
}
四舍五入 Math.round(5.5) // 6
向上取整 Math.ceil(2.1) //3
向下取整 Math.floor(2.9) //2
绝对值 Math.abs(-1) //1
次方 Math.pow(2,3) 2的3次方 //8
平方根 Math.sqrt(9) //3
最大值 Math.max(1,2,3,4,5,6,7) //7
最小值 Math.min(1,2,3,4,5,6) //1
Π Math.PI //3.141592…
json对象
有属性方法的无序的键值对的集合
json对象的作用是:封装信息
为什么需要对象
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组
如果用JS中的对象来表达,结构会更清晰。
var person = {
name: "刘帅", //name 键 //刘帅 值
age: "22",
sex: "男",
height: "175cm",
};
对象里面的属性均是键值对:
- 键:相当于属性名。
- 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)。
- 对象的属性值可以是任何的数据类型,也可以是个函数:(也称之为方法)
json对象
数组 有序的数据集合 有顺序 有下标 有长度 for forEach
json 无序的键值对集合 没顺序 有键 没有长度 for-in
let json={键名:键值,键名:键值}
怎么使用
获取值
json.键名
json[‘键名’]
区别 [ ]里面可以放变量
设置
json.键名 =xxx
json[‘键名’]=xxx
修改
json.键名 =xxx
json[‘键名’]=xxx
键名不能重复
删除
delete json.键名
delete json[‘键名’]
遍历所有内容的
for-in 目的就是为了遍历对象
for(var 随便写的变量代表键 in 要遍历的对象){
//key json[key]
}
Bom(浏览器对象模型)
三个弹窗、定时器
open
- 打开一个页面open(‘地址’)
- 如果直接写,会被浏览器阻止,为了用户体验,不允许直接跳转
- 用户必须操作后才可以跳转,必须在事件里面触发
close
- 关闭一个页面 close(‘地址’)
地址栏
- location是一个对象
- location.href 地址 可以跳转页面的时候用
- location.search 数据 ?后面的内容
- location.hash 锚点 #后面的内容
- location.reload() 刷新
历史记录
- history
- history.forword()前进
- history.back() 后退
- history.go(数字) 1前进一页 -1退回前一页 0当前页面刷新
浏览器信息
navigator.userAgent 可以获取浏览器信息
h5-localstorage 浏览器的本地存储
存:localStorage.setItem(key,value) 存进去的东西都会变成字符串
取:localStorage.getItem(key)
删除:localStorage.removeItem(key)
全部删除:localStorage.clear()
如何把对象变成字符串
JSON.stringify(对象) 转化成字符串
向浏览器存的如果是对象,先转化成字符串再存
把字符串如何变成对象
JSON.parse(字符串-里面是对象的样子) 转化成对象 从浏览器获取出来的如果是字符串的对象 先转化成真正的对象再用
事件触发时候,包含事件详细信息的对象。
函数触发的时候里面有个东西 event
event 不兼容低版本火狐。现在全部兼容
clientX/clientY 可视区的坐标
pageX/pageY 页面的距离坐标 兼容高级浏览器
cancelBubble 阻止事件冒泡
target 触发事件的目标元素
event.preventDefault() 阻止浏览器默认行为
- 右键菜单
- form表单的提交
- 阻止浏览器选中
- 阻止出现禁止标志
定时器
分两种定时器
每隔固定的时间执行
**setinterval **(要执行的函数,间隔时间) 间隔时间 毫秒数
固定的时间后,执行一次
setTimeout(要执行的函数,等待时间) 等待时间 毫秒数
清除定时器
clearinterval、clearTimeout [ 需要先定义一个timer ]
function fn1() {
console.log("帅先生");
}
var timer1 = setTimeout(fn1, 3000);
function fn2() {
console.log("帅二娃");
}
var timer2 = setInterval(fn2, 1000);
clearInterval(timer2);
clearTimeout(timer1);
案例:点击获取验证码的倒计时
<body>
<button id="btn">点击发送验证码</button>
</body>
var aBtn = document.getElementById("btn");
var timer;
var n = 5;
function fn() {
n--;
if (n == 0) {
aBtn.innerHTML = "点击发送验证码";
n = 5;
clearInterval(timer);
aBtn.disabled = false;
} else {
aBtn.innerHTML = n + "秒后重新获取";
}
}
aBtn.onclick = function () {
fn();
aBtn.disabled = true;
timer = setInterval(fn, 1000);
};
案例:秒表
<div id="div1">
<input type="text" value="00:00" />
<button>开始计时</button>
<button>暂停计时</button>
</div>
var oInp = document.getElementsByTagName("input")[0];
var aBtn = document.getElementsByTagName("button");
var n = 0;
var timer;
function toDUb(n) {
if (n < 10) {
return "0" + n;
} else {
return n;
}
}
function fn() {
n++;
var m = Math.floor(n / 60);
var s = n % 60;
oInp.value = toDUb(m) + ":" + toDUb(s);
}
//开始
aBtn[0].onclick = function () {
timer = setInterval(fn, 1000);
aBtn[0].disabled = true;
};
//暂停
aBtn[1].onclick = function () {
clearInterval(timer);
aBtn[0].disabled = false;
};
//重置
aBtn[2].onclick = function () {
oInp.value = "00:00";
clearInterval(timer);
aBtn[0].disabled = false;
n = 0;
};
案例:本月还剩几天
<p>本月还剩++天</p>
var oP = document.querySelector("p");
//console.log(nowMoth);
var oDate = new Date();
var nowMoth = oDate.getMonth() + 1;
var nowYear = oDate.getFullYear();
// console.log(nowYear);
var y = nowYear;
console.log(y);
var m = nowMoth;
function toMonth() {
if (
m == 1 ||
m == 3 ||
m == 5 ||
m == 7 ||
m == 8 ||
m == 10 ||
m == 12
) {
return "本月有31天";
} else if (m == 4 || m == 6 || m == 9 || m == 11) {
return "本月有30天";
} else {
if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {
return "本月有29天";
} else {
return "本月有28天";
}
}
}
toMonth();
console.log(toMonth(m));
获取可视区的大小
document.documentElement.clientWidth
document.documentElement.clientHeight
只兼容高级浏览器
物体的信息
物体占地大小 内容+padding+border
- 元素.offsetWidth
- 元素.offsetHeight
物体内容的大小,内容没有超出 内容+padding 超出了包含超出的大小
- 元素.scrollWidth
- 元素.scrollHeight
物体距离周边的位置 物体距离定位父级的距离,如果没有定位父级,距离body的距离
- 元素.offsetLeft
- 元素.offsetTop
获取出来的是数字不加单位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KMjCSc7l-1662618687474)(https://iknow-pic.cdn.bcebos.com/0eb30f2442a7d933684f93f4aa4bd11372f00155?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_600%2Ch_800%2Climit_1%2Fquality%2Cq_85%2Fformat%2Cf_auto)]
滚动的相关信息
滚动的距离
document.documentElement.scrollTop
document.documentElement.scrollLeft
滚动事件
window.onscroll
面向对象
面向过程和面向对象
面向过程
面向过程:先分析好的具体步骤,然后按照步骤,一步步解决问题。
优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。
缺点:没有面向对象易维护、易复用、易扩展。
面向对象
面向对象(OOP,Object Oriented Programming):以对象功能来划分问题,而不是步骤。
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护。学会封装让别人去调用,把所有相同属性和方法的东西,都抽象成对象的过程
缺点:性能比面向过程低。
特点
1、都可以new出来
- var arr =new Array()
- var json =new Object()
- var reg =new RegExp()
- var data =new Data()
2、一堆属性和方法的集合
- arr.length 属性
- arr.push() 方法
- data.getFullYear() 方法
为什么要面向对象
1、利于团队配合
2、提高效率、节约时间
面向对象的编程思想
面向对象的编程思想:对代码和数据进行封装,并以对象调用的方式,对外提供统一的调用接口。
创建对象:
1、单例模式、单体模式
var obj = {
name: '李郝帅',
age: 22
};
var singleDog = {
name: "帅二娃",
sex: "boy",
age: "22",
isBoy: true,
// 还可以存放一个嵌套的对象
//我们还可以在对象中增加一个方法。以后可以通过singleDog.catch()的方式调用这个方法
catch: function () {
console.log("我是帅二娃!");
},
};
var singleDog = new Object();
singleDog.name = "帅二娃";
singleDog.age = 22;
singleDog.catch = function () {
console.log("我是帅二娃!");
};
console.log(singleDog);
缺点:一次只能造出来一只
2、工厂模式 new Object()
function createSingleDog(name, age) {
//准备空白对象 准备原材料
var SingleDog = new Object();
//添加属性和方法 加工
//向对象中添加属性
SingleDog.name = name;
SingleDog.age = age;
SingleDog.catch = function () {
console.log("我是帅二娃!");
};
//返回对象 将新的对象返回
return SingleDog;
}
var c1 = createSingleDog("文崝", 25);
var c2 = createSingleDog("李郝帅", 35);
console.log(c1, c2);
优点 :批量生产
3、构造函数模式
function createSingleDog(name, age) {
this.name = name;
this.age = age;
this.catch = function () {
console.log("我是帅二娃!");
};
}
/* 当在函数调用前加new:
1.会在函数开始的时候创建一个空白对象。
2.把this指向空白对象。(空白对象赋给this)
3.在函数的最后会把加工后的对象返回出去。
*/
var c1 = new createSingleDog("文崝", 25);
var c2 = new createSingleDog("李郝帅", 35);
console.log(c1, c2);
构造函数:是一种特殊的函数,主要用来创建和初始化对象,也就是为对象的成员变量赋初始值。它与 new 一起使用才有意义
构造函数就是函数,但是他的作用就是造对象,所以取名叫做构造函数。
在工作中,为了让程序猿一眼看来,他是造对象的构造函数,给他一个特征首字母大写
构造函数的创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。
优点;
性能更高,不用管初始化对象,不用管返回
new 一个构造函数的执行流程
new 在执行时,会做下面这四件事:
- 会在函数开始的时候创建一个空白对象。
- 把this指向空白对象。
- 执行构造函数里面的代码,给这个新对象添加属性和方法。
- 返回这个新对象(所以构造函数里面不需要 return)。
4、构造加原型混合模式
把变化的,需要的定制的放在构造函数里面,把不需要变化的,放在原型里面
优点:性能进一步提升,因为相同的东西只执行一遍,相同的东西都在原型(基因)里面继承下来
function createSingleDog(name, age) {
this.name = name;
this.age = age;
}
createSingleDog.prototype = {
catch: function () {
console.log("我是帅二娃!");
},
sex: "nan",
};
var c1 = new createSingleDog("文崝", 25);
var c2 = new createSingleDog("李郝帅", 35);
console.log(c1, c2);
c1.catch;
c1.sex();
常用布局
定宽布局
大部分用float
外面的容器是定宽, 里面的内容用百分比 里面的内容也可以放缩
最大值最小值定宽 min-width max-width width:100%
响应式布局
利用媒体查询
在不同终端都能适配的一种布局。
手机,pad,电脑屏幕
移动端刚刚出来。如果要写一个官网,则移动端写一个,pc端写一个,pad端写一个
能不能写一套代码,所有浏览器都适用。
自适应布局
弹性布局+rem布局
媒体查询
根据屏幕的宽度来进行判断
不同的尺寸写不同的样式。虽然是一套代码,但是是多套样式
有很多局限性
1、结构有局限性
2、不能特别复杂
媒体查询用于什么地方
1、简单的官网
2、都是产品的商品网站
3、文档类的网站
用媒体查询做一些小块的修改