一、对象
-
对象的创建
- 形式 字面量(var,let,cont) 变量名 = {键值对}
- 方法 new Object()
var obj = {
name: 'baozi',
age: 18
}
console.log(obj);
var nobj = new Object();
console.log(nobj);
-
操作对象的属性
-
添加属性
- 点语法 对象.属性名 = 属性值;
- [] 语法 对象["属性名"] = 属性值;
-
注意事项:
- 添加属性值的时候,如果是字符串形式,一定要加上引号
- 在使用[]方法的时候,中括号里的属性名也要加上引号
obj.sex = "男";
console.log(obj)
nobj["name"] = "rbz";
console.log(nobj);
-
更改属性值
- 可以使用添加属性值的方法进行更改
obj.sex = "nan";
console.log(obj)
nobj["name"] = "肉包子";
console.log(nobj);
-
删除属性
- 方法 delete 对象名.属性名
delete obj.age;
console.log(obj);
-
查找属性值
- 方法 对象名["属性名"]
console.log(obj["name"]);
二、运算符
-
算数运算符
- +(加) -(减) *(乘) 、(除) %(取余)
-
比较运算符
-
>(大于号),<(小于号) ,>= (大于等于),<=(小于等于) ,== (等于号) ,!=(不等于) , ===(全等号 要求值和数据类型都一致),!==(不全等)
-
注意:
- 比较运算符返回的结果是布尔值,true或者是false
- 一个等于号是复制,将右边的数据赋值给左边的变量
- 两个等号是判断是否相等,只会比较数值大小,不会进行数据类型的比较,只需要数据大小相同即可 console.log(18 == '18') // true
- 三个等号就是既要要求数据大小,也要要求数据类型相同 console.log(18 == '18') // false
- 不等于和不全等这两个返回值是双等和三等号的相反值,如果不等为false,那么与之对应的双等就是true,反之则是false。
var a = 10,
b = "10",
c = '20';
console.log(a !== b) //true
console.log(a == b) //true
console.log(a != b) //false
console.log(a != c) //true
console.log(a === c) //false
console.log(a !== c) //true
-
自增 ++ 和自减--
-
自增++
-
使用口诀:先自加,后返回值 ++num => num = num+1
-
-
var num = 10;
alert (++num + 10); // 21
console.log(num) //11
- 自减--
-
使用口诀:先返回原值,后进行自加
-
var num = 10;
alert(10 + num--); // 20
console.log(num) //9
注意
-
前置递增和后置递增运算符可以简化代码的编写,让变量的值 + 1 比以前写法更简单
-
单独使用时,运行结果相同,与其他代码联用时,执行结果会不同
-
开发时,大多使用后置递增/减,并且代码独占一行
-
逻辑运算符
- 逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值
- &&(逻辑与) ||(逻辑或) !(逻辑非)
- 逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值
true && false // false
true || false // true
!true // false
-
赋值运算符
- =(直接赋值) +=(加上一个数字再等于) -=(减去一个数字再等于) *= /= %= 乘,除,取模后再赋值
var age = 10;
age += 5; // 相当于 age = age + 5;
age -= 5; // 相当于 age = age - 5;
age *= 10; // 相当于 age = age * 10;
-
运算符的优先级(优先级从上到下)
- 小括号 ()
- 一元运算符 +,-,++,--,!
- 算数运算符 先 * / 后 + -
- 关系运算符 >,>=,
- 相等运算符 ==,===,!== ,!=
- 逻辑运算符 先与运算,后或运算
- 赋值运算符 =
- 逗号运算符
注意:
-
一元运算符里面的逻辑非优先级很高
-
逻辑与要比逻辑或的优先级高
三、流程控制语句
流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序
-
分支结构
-
if语句
-
if
-
if(条件表达式){
//条件成立的时候,执行里面的代码语句
}
-
if else
if(条件表达式){
//条件成立的时候,执行里面的代码语句
}else{
//否则,条件不成立的时候,执行里面的代码语句
}
-
if else if else
if(条件表达式1) {
语句1;
} else if(条件表达式2) {
语句2;
} else if(条件表达式3) {
语句3;
} else {
*//上述条件都不成立执行此处代码*
}
-
三元表达式
语法结构:表达式1?表达式2:表达式3
如果表达式1为true,则返回表达式2的值,如果表达式1为false,则返回表达式3的值
var figuer = prompt('请输入0~59之间的一个数字');
var result = figuer < 10 ? '0' + figuer : figue
alert(result);
-
switch语句
switch :开关 转换 , case :小例子 选项
关键字 switch 后面括号内可以是表达式或值, 通常是一个变量
关键字 case , 后跟一个选项的表达式或值,后面跟一个冒号
-
执行流程
switch 表达式的值会与结构中的 case 的值做比较
如果存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代码执行结束
如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码
执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句
switch(表达式){
case value1:
//表达式等于 value1 时要执行的代码
break;
case value2:
//表达式等于value2 时要执行的代码
break;
default:
//表达式不等于任何一个value时要执行的代码
}
-
示例
var fruit = prompt('请您输入查询的苹果');
switch (fruit) {
case '苹果':
alert('苹果的价格为3.5元/千克');
break;
case '香蕉':
alert('香蕉的价格为3元/千克');
break;
default:
alert('没有这种水果');
}
-
循环语句
-
for循环
在程序中,一组被重复执行的语句被称之为循环体,能否继续重复执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,被称之为循环语句。
for(初始化变量;条件表达式;操作表达式) {
//循环体
}
-
示例
-
输出10句 你好!
for(var i = 1; i<=10; i++ ){
console.log('你好');
}
-
输出一行比一行多一个星星,一共十行
var star = ""
for(var a =0 ;a<10 ;a++){
star += "*";
console.log(star)
}
-
双重for循环
循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在for循环语句中,可以再嵌套一个for 循环,这样的 for 循环语句我们称之为双重for循环。
for(外循环的初始;外循环的条件;外形循环的操作表达式){
for(内循环的初始;内循环的条件;内循环的操作表达式){
需执行的代码;
}
}
-
注意:
- 内层循环可以看做外层循环的语句
- 内层循环执行的顺序也要遵循 for 循环的执行顺序
- 外层循环执行一次,内层循环要执行全部次数
-
示例:
-
打印五行五列五角星
var star = '';
for(var j = 1;j<=5;j++)
{
for (var i = 1; i <= 5; i++)
{
star += '☆'
}
//每次满5个星星就加一次换行
star +='\n'
}
console.log(star);
-
打印倒三角
var star = '';
var row = prompt('请输入行数');
var col = prompt('请输入列数');
for (var i = 1; i <= row; i++) {
for (var j = i; j <= col; j++) {
star += '☆';
}
star += '\n';
}
console.log(star);
-
while循环
-
执行逻辑
-
先执行条件表达式,如果结果为 true,则执行循环体代码;如果为 false,则退出循环,执行后面代码
-
执行循环体代码
-
循环体代码执行完毕后,程序会继续判断执行条件表达式,如条件仍为true,则会继续执行循环体,直到循环条件为 false 时,整个循环过程才会结束
-
-
注意:
-
使用 while 循环时一定要注意,它必须要有退出条件,否则会称为死循环
-
while 循环和 for 循环的不同之处在于 while 循环可以做较为复杂的条件判断,比如判断用户名和密码
-
-
示例:
-
打印从1到99
var age = 0;
while (age <= 100) {
age++;
console.log('您今年' + age + '岁了');
}
- 计算1~100的和
var figure = 1;
var sum = 0;
while (figure <= 100) {
sum += figure;
figure++;
}
console.log('1-100的整数和为' + sum);
-
do while循环
-
执行逻辑
- 先执行一次循环体代码
- 再执行表达式,如果结果为true,则继续执行循环体代码,如果为false,则退出循环,继续执行后面的代码
- 先执行再判断循环体,所以dowhile循环语句至少会执行一次循环体代码
do {
//循环体代码-条件表达式为true的时候重复执行循环一代码
}while(条件表达式);
-
示例
-
弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问
do {
var love = prompt('你爱我吗?');
} while (love != '我爱你');
alert('登录成功');
-
continue 关键字
用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。
//例如,吃5个包子,第3个有虫子,就扔掉第3个,继续吃第4个第5个包子
for (var i = 1; i <= 5; i++) {
if (i == 3) {
console.log('这个包子有虫子,扔掉');
continue; // 跳出本次循环,跳出的是第3次循环
}
console.log('我正在吃第' + i + '个包子呢');
}
-
break 关键字
break 关键字用于立即跳出整个循环
//吃5个包子,吃到第3个发现里面有半个虫子,其余的也不吃了
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 直接退出整个for 循环,跳到整个for下面的语句
}
console.log('我正在吃第' + i + '个包子呢');
}
-
四、this与自定义属性
-
this关键字
this默认指向的是当前元素,全局函数中的this指向window对象
代码中声明了一个全局函数,是属于浏览器窗口对象的,所以this表示的就是浏览器窗口对象window
function fn() {
consolo.log(this);
}
fn()
//标签事件属性中的this指向window对象
如果将一个全局函数在一个标签属性中调用,如下
<button onclick="fn()">点我试试</button>
function fn() {
console.log(this)
}
//事件属性函数中的this指向当前操作的标签
如果在标签对象的属性上声明了一个函数,此时这个函数属于标签属性,所以函数内部的this指向当前标签对象
<button id="btn">点我试试</button>
var btn = document.getElementById('btn');
btn.onclick = function() {
console.log(this);
}
-
自定义属性
// 自定义属性:自己定义
// 固有属性:系统提供的
var oDiv = document.getElementsByTagName("div");
console.log(oDiv[0].tag); //unfined 暂时获取不到直接写在标签上的自定义属性
//1.在js中添加自定义属性 标签.属性名
oDiv[0].tag = true;
console.log(oDiv[0].tag);
-
五、初级函数
-
函数声明
-
// 函数表达式
var f = function() {
console.log(1);
}
// 函数声明
function f (){
console.log(2);
}
// 调用
f()
-
形参和实参
-
形参:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
-
实参:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
-
// 函数内部是一个封闭的环境,可以通过参数的方式,把外部的值传递给函数内部
// 带参数的函数声明
function 函数名(形参1, 形参2, 形参3...) {
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3);
形参1 = 实参1
形参2 = 实参2
形参3 = 实参3
...
注意事项:
函数最终的运算结果由实参所解决定;
不论形参还是实参,都不需要关键字“var”的显示声明,函数的参数只能在函数内部访问。
形参与实参是通过位置而不是参数名来匹配对应的
形参与实参的个数可以不一致
如果一个形参没有接收到实参传递来的值,那么他为undefined
在实参数量未知的时候可以使用arguments。arguments代表了一个函数的所有参数,他是一个类似数组的东西,可通过下标取值。在我们不知道具体的参数个数时,尤为有用。
-
返回值
当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值。
每一个函数都会有一个返回值,这个返回值可以通过关键字“return”进行设置。
//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参3...) {
//函数体
return 返回值;
}
//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3...)
注意事项:
若未显式地设置函数的返回值,那函数会默认返回一个undefined值
但若手动地设置了函数的返回值(return)后,函数将返回开发者手动设置的那个值
在函数中,一旦执行完成“return”语句,那么整个函数就结束了,后续语句将不再执行;
就是“return”之后的值只能有一个。如果尝试返回多个值,那得到的结果始终是最后一个值
-
预解析与作用域
-
作用域
在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
就是代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性更重要的是减少命名冲突
作用域的划分全局作用域:整个script标签 或者是一个单独的js文件,script标签以内,函数体以外称之为全局作用域
<script>
var num = 10;
var num = 30;
console.log(num);
</script>
局部作用域:函数执行形成局部作用域(私有作用域)在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用。
function fn() {
// 局部作用域
var num = 20;
console.log(num);
}
fn();
全局变量和局部变量全局变量(全局函数):全局作用域下定义的变量就属于全局变量,可以在任意地方使用或修改
// 注意 如果在函数内部 没有声明直接赋值的变量也属于全局变量
var num = 10; // num就是一个全局变量
console.log(num);
function fn() {
console.log(num);
}
fn();
局部变量(局部函数):局部作用域下定义的变量就属于局部变量,只能在当前作用域下使用或修改
// 注意: 函数的形参也可以看做是局部变量
function fun(aru) {
var num1 = 10; // num1就是局部变量 只能在函数内部使用
num2 = 20;
}
fun();
从执行效率来看全局变量和局部变量
(1) 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
(2) 局部变量 当我们程序执行完毕就会销毁, 比较节约内存资源
js中没有块级作用域 js的作用域: 全局作用域 局部作用域 现阶段我们js 没有 块级作用域
我们js 也是在 es6 的时候新增的块级作用域
块级作用域 {} if {} for {}
-
预解析
- 预解析 js引擎会把js 里面所有的 var 还有 function 提升到当前作用域的最前面
- 代码执行 按照代码书写的顺序从上往下执行
- 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
- 变量提升 就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
- 函数提升 就是把所有的函数声明提升到当前作用域的最前面 不调用函数
- 预解析可以分为:
- 全局作用域下的预解析
- 局部作用域下的预解析
- 预解析发生在js代码真正执行之前,先进性预解析的操作,把所有带有var和functiuon关键的进行预解析,var进行预解析是只声明不定义,funtion在预解析的时候是声明+定义
- 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
-
函数封装
函数 是由事件驱动的或者当它被调用时执行的可重复使用的代码块。 用函数把重复的代码块包裹起来就是函数封装。
封装的作用: 其实就是为了减少代码的冗余,增加代码的可读性与易维护性, 将实现同一功能的代码封装起来,在需要实现这一功能时调用即可。
-
六、匿名函数和密保
-
匿名函数
-
匿名函数就是没有函数名的函数,但是这样写的话,会报错,所以为了解决这个问题我们可以从多个角度进行解决
-
-
// 1.把匿名函数赋值给一个变量
var box=function(){
return 'Hex';
}
alert(box());
// 2.通过自我执行来调用函数
(function(){
alert('Hex');
})();
// 3. 把匿名函数自我执行的返回值赋值给变量
var box=(function(){
return 'Hex';
})();
alert(box);//注意:此处不带括弧
// 4.省去变量
alert((function() {
return 'Hex';
})());
// 5.在使用的时候如何传参
(function(age) {
alert('Hex--' + age);
})(30);
-
闭包
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
var n=999;
function f1(){
alert(n);
}
f1(); // 999
另一方面,在函数外部无法读取函数内的局部变量。
function f1(){
var n=999;
}
alert(n); // error
这里有一个地方需要注意, **函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!**
function f1(){
n=999;
}
f1();
alert(n); // 999
-
作用
-
通过一系方法,将函数内部的变量(局部变量)转化为全局变量
-
子级可以调用父级的变量,而父级无法调用子级的变量
-
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
-
七、定时器
js的定时器有两种定时器,一个是延迟执行,一个是间断执行
//setTimeout():指定时间后执行一段代码(延迟执行)。
//setInterval():每隔一段时间执行一段代码(间隔执行)。
//延迟执行
setTimeout(function(){
console.log(111);
},1000) //一秒钟打印出111
//间隔执行
setInterval(function(){
console.log(111);
},1000) //每隔一秒钟打印出111
-
清除定时器
每次使用定时器时,必须清除定时器
clearTimeout(timer) ====> 用于清除setTimeout
clearInterval(timer) ====> 用于清除setInterval
示例:
//在开启定时器的同时定义一个变量接受定时器返回的id,用于清除定时器
var timer=setTimeout(function(){
console.log(111);
},1000)
// 使用清除延迟定时器
clearTimeout(timer);
var timer2=setInterval(function(){
console.log(111);
},1000)
// 使用清除间歇定时器
clearInterval(timer2);
-
八、内置对象
-
什么是内置对象
-
根据JS API(开发文档说明)(Application Program Interface)讲解的内置对象就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或者最基础而且最必要的功能(常用的属性、函数等)
-
-
math对象
-
常用方法
// 向下取整,不会四舍五
console.log(Math.floor(3.99)) //3
// 向上取整,会四舍五
console.log(Math.ceil(3.56)) //4
// 四舍五入法
console.log(Math.round(3.6)) //4
// Math.max():获取数组序列中最大的值
console.log(Math.max(5,20)) //20
// Math.min():获取数组序列中最小的值
console.log(Math.min(5,20)) //5
// 计算某个数组的次方数 计算5的20次方
console.log(Math.pow(5,20)) //95367431640625
// 开平方根
console.log(Math.sqrt(100)) //10
// 获取随机数 范围是(0,1)
console.log(Math.random())
- 应用
// 1.随机一个整数
Math.round(Math.random()*10)
//或者是从0-10之间的整数
parseInt(Math.round()*10)
// 2.指定一个任意整数的范围
// 指定一个范围整数取随机整数,并且要求包含这两个整数
function randomNum(min,max){
return Math.floor(Math.random()*(max-min+1)+min);
}
// 3.随机点名系统
<p id="name"></p>
<button type="button">确定</button>
<button type="button">开始</button>
<script>
var namelist = [
"老李",
"老王",
"老张",
"老赵",
"老钱",
"老孙",
"老周",
"老吴",
"老郑",
"老程",
];
var p = document.getElementById("name")
var btnEnd = document.getElementsByTagName("button")[0];
var btnStar = document.getElementsByTagName("button")[1];
function qiehuan() {
var index = parseInt(Math.random() * namelist.length);
p.innerText = namelist[index]
}
var timer = setInterval(qiehuan, 1);
btnEnd.onclick = function () {
clearInterval(timer)
}
btnStar.onclick = function(){
timer = setInterval(qiehuan, 1);
}
</script>
// 4.生成随机验证码
var str = "safsdfa564x1b54x5g1e51654b64h64e6aGDG6sg6g46sd4f8eG";
var p = document.getElementsByTagName("p")[0]
// 第一种方法
function randomNum(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
var item = randomNum(0, str.length - 6);
var a = str.substring(item, item + 5);
p.innerHTML ="第一种方法生成的验证码 "+ a;
// 第二种方法
var str1 = "abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQISTUVWXYZ0123456789";
var p2 = document.getElementsByTagName("p")[1]
var res = ""
for (let a = 0; a < 5; a++) {
let index = parseInt(Math.random() * str1.length)
res += str1.charAt(index)
}
console.log(res)
p2.innerHTML ="第二种方法生成的验证码 "+ res;
-
Date对象
date主要是用来处理日期和时间
获取当前时间,使用date对象必须要实例化
var time = new Date();
获取指定时间的日期对象
var time=new Date("2021,10,1");
//语法解释
利用new来声明一个新的的对象实体,使用new操作符的语法如下:
var 实例对象名称 = new 对象名称(参数列表)
date对象常用的方法
//Date 操作日期和时间的对象
Date.getFullYear() //返回Date对象的年份字段
Date.getMonth() //返回月份数(0-11),想要几月的话,需要加一
Date.getDay() //返回一周的第几天(0-6) 0 代表周日
Date.getDate() //返回日期的“日”部分,值为1~31
Date.getHours() //返回日期的“小时”部分,值为0~23
Date.getMinutes() //返回日期的“分钟”部分,值为0~59
Date.getSeconds() //返回日期的“秒”部分,值为0~59
Date.getTime() //返回从1970年1月1日00:00到现在的毫秒数(格林尼治时间),也就是时间戳
Date.setFullYear() //设定日期的“年”部分
Date.setMonth() //设定日期的“月”部分,值为0~11。其中0表示1月,…,11表示12月
Date.setDate() //设定日期的“日”部分,值为0~31
Date.setHours() //设定日期的“小时”部分,值为0~23
Date.setMinutes() //设定日期的“分钟”部分,值为0~59
Date.setSeconds() //设定日期的“秒”部分,值为0~59
示例
var date = new Date();
console.log(date);
year = date.getFullYear();
console.log("当前年份是", year);
month = date.getMonth() + 1;
console.log("当前月份是", month); //0为一月,比实际少1个月 所以要想获取当前的实际日期,需要+1
date1 = date.getDate();
console.log("当前日期", date1)
day = date.getDay();
console.log("当前星期", day) //0为星期天
time = date.getTime();
console.log("当前时间", time); //返回从1970年1月1日00:00到现在的毫秒数(格林尼治时间),也就是时间戳
hour = date.getHours();
console.log("当前时间的小时", hour) //24小时制
minutes = date.getMinutes();
console.log("当前时间的分钟", minutes);
seconds = date.getSeconds();
console.log("当前时间的秒数", seconds) //毫秒为单位
-
String对象
常用方法
String //操作字符串的对象
length属性 //获取字符串的长度
charAt(下标) //获取对应位置的字符
indexOf(str[,index]) //返回某个指定的字符串值在字符串中首次出现的位置
lastIndexOf(str[,index]) //返回某个指定的字符串值在字符串中最后一次出现的位置
substring([start,[stop]]) //截取字符串,从start到stop,包括开始不包括结束 。
slice([start,[stop]]) //截取字符串
toUpperCase //转换为大写
toLowerCase //转换为小写
split //(分割标准,[数组的长度]) : 将字符串按特定标志分割成数组
replace //(被替换的字符串,替换的字符): 替换特定的字符
实例演示
var str = "asdfsdgcxhedfgshsRSFssdg";
console.log(str)
console.log("长度为", str.length); //24
console.log("下标为5(第六个字母是)", str.charAt(5)); //d
console.log("h第一次出现的下标是", str.indexOf("h")); //9
console.log("s最后一次出现的下标是", str.lastIndexOf("s")); //21
console.log("查看是否存在l,如果存在则返回对应的下标,如果不存在则返回-1", str.indexOf("l")); //-1
// substring
//从下标为0的地方开始截取,一直截取到下标为4的位置(不包括自己缩写的结束下标)
var a = str.substring(0, 5);
console.log(a) //asdfs
// 如果只有开始位置,那么代表的意思就是从这个下标开始一直到结束
a = str.substring(1);
console.log(a); //sdfsdgcxhedfgshsRSFssdg
//如果参数为负数,那么代表的意思是0
a = str.substring(-1,3);
console.log(a) //asd
// 如果开始参数的位置在结束参数位置的右侧,截取结果为结束位置到开始位置之间所有的字符,但不包括开始位置的字符(也就是将两个参数位置对调,开始参数变为结束参数,结束参数变为开始参数)
a = str.substring(4,1);
console.log(a) //sdf
// 如果开始和结束位置一样,结果为空
a = str.substring(1,1);
console.log(a)
// slice
//从下标为0的地方开始截取,一直截取到下标为4的位置(不包括自己缩写的结束下标)
var a = str.slice(0, 5);
console.log(a) //asdfs
// 如果只有开始位置,那么代表的意思就是从这个下标开始一直到结束
a = str.slice(1);
console.log(a); //sdfsdgcxhedfgshsRSFssdg
//如果参数为负数,那么代表的意思是从右往左数(倒序-1,-2,-3……),
a = str.slice(-1);
console.log(a) //g
a = str.slice(-5,-1);
console.log(a) //Fssd
a = str.slice(-5,22);
console.log(a) //Fss
// 如果开始参数的位置在结束参数位置的右侧,截取结果为空
a = str.slice(3,0);
console.log(a) //空
// 如果开始和结束位置一样,结果为空
a = str.slice(1,1);
console.log(a) //空
// 大小写切换 不会对原字符串产生任何的影响
var b = str.toUpperCase(); //将该字符串全部转换成大写
console.log(b) //ASDFSDGCXHEDFGSHSRSFSSDG
b = str.toLowerCase(); //将该字符串全部转换成小写
console.log(b) //asdfsdgcxhedfgshsrsfssdg
// 切割字符串 split 不会对原字符串产生影响
var arr = "2022-12-23";
var arr1 = arr.split("-"); //按照特定的字符“-”,将字符串进行切割
console.log(arr1) //(3) ['2022', '12', '23']
console.log(arr) //2022-12-23
//替换特定的字符 replace 不会对原字符串产生影响,且只执行一次
var arr2 = arr.replace("-",'*')
console.log(arr2)//2022*12-23
console.log(arr) //2022-12-23
// 将数组转换为字符串
// 第一种方法 通过使用toString()方法将其强制转换为字符串,然后通过替换进行替换(此处用到了正则,g代表的是执行全局匹配[查找所有匹配而非在找到第一个匹配后停止)
var arr3 = arr1.toString().replace(/,/g,'-');
console.log(arr3) //2022-12-23
console.log(arr1) //(3) ['2022', '12', '23']
// 第二种方法
var arr4 = arr1.join('*');
console.log(arr4); //2022*12*23
console.log(arr1) //(3) ['2022', '12', '23']
// 检索字符串中指定的子字符串 search()
/*
搜索单个字符
如果字符串里面有,则返回它所对应首次出现的下标
如果字符串里没有,则返回-1
搜索多个字符组合
如果字符串里面有,则返回它们整体首次出现中的第一个字符的下标
如果字符串里没有,则返回-1
*/
var arr5 = "asdfa"
console.log(arr5.search("a")) //0
console.log(arr5.search("sd")) //1
console.log(arr5.search("e")) //-1
console.log(arr5.search("ae")) //-1
// 可在字符串内检索指定的值 match() 一般与正则表达式进行联合使用
var arr6 = "asd asd asd ASD aSd lasd wdsa";
console.log(arr6.match(/asd/g))
注意:
slice与substring的区别在于当接收的参数是负数时,slice会将它字符串的长度与对应的负数相加,结果作为参数。substring则干脆将负参数都直接转换为0
示例演示2:
// 文字展开收缩
<div>
<p>为贯彻落实党中央、国务院决策部署,12月21日,教育部会同中央网信办、公安部、国家疾控局召开2023年研考工作调度会。教育部党组书记、部长怀进鹏出席会议并讲话,教育部党组成员、副部长翁铁慧主持会议。会议要求,各地各部门要提高政治站位,强化政治执行力,落实安全稳定责任,全力以赴抓好研考组织工作。各地要调集动员专门力量,优先保障考生核酸检测,及时向考生和考点反馈核酸检测结果。加强考场防疫管理,配足配齐防疫物资。要加强组考管理,确保考试安全。要严格执行安全保密规定,确保试卷流转绝对安全,严格落实入场和考场监督检查要求,严厉打击考试作弊,严肃处理各类违规违纪行为。会议要求,各地各有关部门要加强服务保障,关心关爱广大考生和考务工作人员。要坚持以生为本,优化考生服务,加强政策宣传解读,及时告知考生组考防疫安排,及时回应和妥善解决考生急难愁盼的问题,积极为特殊困难考生参加考试提供合理便利。要关心考务工作人员,创造有利条件,为广大考务工作人员,尤其是监考老师,提供安全暖心的工作环境。中央网信办、公安部、国家疾控局有关负责同志出席会议,并就做好研考考试环境综合治理和组考防疫工作作了讲话。河南省、广东省有关负责同志发言。会议在北京设主会场,各省、自治区、直辖市设分会场。各省(区、市)高校招生委员会主任、有关部门负责同志及各省教育行政部门、招生考试机构主要负责同志参加会议。
</p><span>收缩</span>
</div>
<script>
var p = document.getElementsByTagName("p")[0];
var str = p.innerText;
var span = document.getElementsByTagName("span")[0];
var a = 0;
span.onclick = function () {
a++;
if (a % 2) {
span.innerHTML = "展开";
p.innerHTML = str.slice(0, 50) + "……";
} else {
span.innerHTML = "收缩";
p.innerHTML = str;
}
}
</script>
-
数组
-
数组(Array)是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素可以放数组,字符串,数字,集合对象等,所有的都可以放
//普通变量一次只能存储一个值
var num = 10;
//数组一次可以存储多个值
var arr =[1,2,3,4,5];
-
创建数组
//第一种方法:利用 new 创建数组
var 数组名 = new Array();
var arr = new Array(); //创建一个新的空数组
//第二种方法:利用数组字面量创建数组
// 1.利用数组字面量方式创建空的数组
var 数组名 =[];
// 2.使用数组字面量方式创建带初始值的数组
var 数组名 =['小白','小黑','小黄','瑞奇'];
// 3.数组中可以存放任意类型的数据,例如字符串,数字,布尔值等
var arrStus =['小白',12,true,28.9];
注意:
- 数组的字面量是方括号 []
- 声明数组并赋值称为数组的初始化
- 这种字面量方式也是我们以后最多使用的方式
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0, "a", null, false, undefined, [5, 7]];
// 1.push() 向数组的末尾添加一个或多个元素,并返回新的长度
// 返回的是一个新数组的长度,要想获取新数组,直接打印原数组即可,如果想要添加多个,,直接使用逗号隔开即可
var a = arr.push("{aa:1}", "aa")
console.log(arr)
console.log(a)
// 2.pop() 删除并返回数组的最后一个元素
// 返回的是原数组最后一项的数据,如果打印原数组,那么获取到的是删除完之后的数据,想要获取被删除的数据,需要拿一个新的变量进行存取
var b = arr.pop()
console.log(arr)
console.log(b)
// 3.shift() 删除并返回数组的第一个元素
//返回的是原数组第一项的数据,如果打印原数组,那么获取到的是删除完之后的数据,想要获取被删除的数据,需要拿一个新的变量进行存取
var c = arr.shift()
console.log(arr)
console.log(c)
// 4.unshift():向数组的开头添加一个或更多元素,并返回新的长度。
//返回的是一个新数组的长度,要想获取新数组,直接打印原数组即可,如果想要添加多个,直接使用逗号隔开即可
var d = arr.unshift(1, "aa")
console.log(arr)
console.log(d)
// 5.splice()
//5.1 删除数组元素 数组.splice(index,howmany) ,从下标为index开始,一直删除howmany个元素
//所返回的数据是被删除的内容,需拿一个变量进行存储,直接打印原数组是直接打印被删除之后的数组
var e = arr.splice(1, 5) //删除数组,从下标为一的位置开始删除,然后一直删除5个元素
console.log(arr)
console.log(e)
// 5.2 替换数组元素 数组.splice(index,howmany,item1,)
//所返回的数据是被删除的内容,需拿一个变量进行存储,直接打印原数组是直接打印被替换之后的数组
// 然后将替换的元素全部加入到被删除元素的原位置上,
// 添加元素的个数是自己后面item位置上所包含的数量,有几个添加几个
var f = arr.splice(1, 2, "a", "b", "c")
console.log(arr)
console.log(f)
// 5.3插入数组元素:splice(1,0,'a') 从下标为1开始,删除0个,字符a插入在下标为1的位置,其他的数组元素往后移动
//其返回值是一个空数组
// 添加元素的个数是自己后面item位置上所包含的数量,有几个添加几个
var g = arr.splice(1, 0, "aa", "bb");
console.log(g)
console.log(arr)
// 6.数组排序
// console.time()
arr = [1, 2, 1, 2, 4, 2, 5, 5, 5, 8, 4, 849, 76, 46, 6, 46];
// arr.sort(function(a,b){
// return a-b;
// })
// console.log(arr)
// index = 0
var arr= [1,5,7,9]
// sort会改变原数组的顺序
arr.sort(function(a,b){
return a-b //返回负数,数组正序(从小到大)
// return b-a //返回正数,数组逆序(从大到小进行排序)
})
console.log(arr)
注意:
- 删除数组元素:splice(1,3) 从下标为1开始,删除3个数组元素
- 替换数组元素:splice(1,2,'a','b') 从下标为1开始,删除2个数组元素,使用字符a,b代替删除的元素。
- 插入数组元:splice(1,0,'a') 从下标为1开始,删除0个,字符a插入在下标为1 的位置,其他的数组元素往后移动
// 1、使用原生js进行数组内部排序
// 选择法
// console.time()
var arr = [8, 5, 3, 1, 7, 2, 9, 6] //定义一个数组
for (var j = 0; j <= arr.length - 1; j++) { //定义一个for循环,循环次数为它的长度-1取索引值
var minIndex = j; //定义一个变量表示索引用来遍历数组
for (var i = j + 1; i <= arr.length - 1; i++) { //定义一个for循环,循环次数为它的长度-1,j+1变量赋值给i,此处循环的是arr[j]后面的所有元素
if (arr[minIndex] > arr[i]) { //判断如果左边索引值的元素比右边索引值的元素大,则换位
minIndex = i;
}
}
var tmp = arr[minIndex] //定义一个变量用于交换索引值,先把上面得到的最小值赋给tmp
arr[minIndex] = arr[j] //再把当时最小值跟第一位的值交换一下
arr[j] = tmp
//console.log(tmp) //输出tmp被赋予的最小值
// console.log(arr[j]) //此时数组的第一位就是最小值,因为它的索引已经被跟之前的第一位值索引调换位置
}
console.log(arr) //打印输出,结果为:Array(8) [ 1, 2, 3, 5, 6, 7, 8, 9 ]
// console.timeEnd()
// 冒泡法
var arr = [8, 5, 3, 1, 7, 2, 9, 6,1] //定义一个无序数组
for (var j = 0; j <= arr.length - 1; j++) {
// 定义一个变量j表示循环数组的长度 - 1 次
for (var i = 0; i <= arr.length - 1; i++) { //定义一个变量i表示循环数组的长度-1次
if (arr[i] > arr[i + 1]) { //判断索引为i的值比索引为i+1的值大,则进行换位
var tmp = arr[i]; //定义一个变量tmp,给它赋值索引为i的元素
arr[i] = arr[i + 1] //把索引为i的元素覆盖为索引为i+1的元素
arr[i + 1] = tmp //再把tmp的值赋给索引为i+1的值
}
}
}
console.log(arr) //最后打印数组,结果:Array(8) [ 1, 2, 3, 5, 6, 7, 8, 9 ]
var arr = [0,1,2,4,3];
// 1.join(): 将数组按特定标志组合成字符串
// 不会对原数组产生任何的改变
var arr1 = arr.join("*")
console.log(arr1)
console.log(arr)
// 2.reverse() : 将数组倒序表示,并返回
// 会对原数组产生影响
arr1 = arr.reverse()
console.log(arr1)
console.log(arr)
// 3.concat(): 将多个数组组合成一个新数组返回
// 不会对原数组产生任何的改变
var arr2 = arr1.concat(arr);
console.log(arr2)
console.log(arr1)
console.log(arr)
// 4.indexOf():在数组中查找指定的元素,找到返回对应的位置,找不到返回-1
// 不会对原数组产生任何的改变
a = arr.indexOf(1);
console.log(arr)
console.log(a)
// 2、数组递归
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var a = arr.slice(1, 5);
console.log(arr)
// [
// 1, 2, 3, 4, 5,
// 6, 7, 8, 9
// ]
console.log(a) // [ 2, 3, 4, 5 ]
// every 针对数组元素做些判断,如果结果都为true 则返回的结果为true
arr = [true, false, true]
var b = arr.every(function (value, index) {
console.log(value)
console.log(index)
return value === true
})
console.log(b)
// some : 针对数组元素做些判断,如果结果有一个为true 则返回的结果为 true
var c = arr.some(function (value, index) {
console.log(value)
console.log(index)
return value === true
})
console.log(c)
// filter : 针对数组元素做些判断,满足条件的元素,会组成一个新的数组,并且返回
// 但不会改变原数组
arr = [1, 2, 3, 4, 5, 6]
var d = arr.filter(function (item, index) {
return item > 3
})
console.log(arr)
console.log(d);
// map : 返回一个新的数组
// 不会改变原数组
// 当条件是判断的时候,返回的新数组是由true和false组成的,满足条件的返回true,不满足条件的返回false
var e = arr.map(function (item, index) {
return item > 3
})
console.log(arr)
console.log(e);
// forEach : 没有返回值,就是一个简单的循环 参数分别为:遍历的数组内容;第对应的数组索引,数组本身。
arr.forEach(function (item, index) {
console.log(item)
})
例题示例:
// 1、使用forEach,将数组里面的name属性重组到一个新数组里面
var newArr = [];
var arr = [
{
id:1,
name:"周一",
},
{
id:2,
name:"周二",
},
{
id:3,
name:"周三",
},
{
id:4,
name:"周四",
},
{
id:5,
name:"周五",
},
{
id:6,
name:"周六",
},{
id:7,
name:"周天",
}
];
arr.forEach(function(item,value){
// console.log(item.name)
newArr.push(item.name)
})
console.log(newArr)
-
九、DOM(文档对象模型)
-
获取元素
-
// 通过getElementById获取的
//getElementById是通过标签的 id 名称来获取标签的
<body>
<div id="box"></div>
<script>
var box = document.getElementById('box');
console.log(box); // <div></div>
</script>
</body>
// 通过getElementsByClassName获取
//getElementsByClassName是通过标签的 class 名称来获取标签的
//所获取的是一个类数组,可以通过下标进行选择
<body>
<div calss="box"></div>
<script>
var box = document.getElementsByClassName('box');
console.log(box); // [<div></div>]
console.log(box[0]); // <div></div>
</script>
</body>
//获取到的是一组元素,是一个长的和数组一样的数据结构,但不是数组,是伪数组
// 这一组数据也是按照索引排列的,所以我们想要准确的拿到这个 div ,需要用索引来获取
//无论是几个,哪怕是一个,所获取到的也是一个类数组的形式
//通过getElementsByTagName获取
//getElementsByTagName是用标签的 标签名 来获取标签的
//所获取的是一个类数组,可以通过下标进行选择
<body>
<div></div>
<script>
var box = document.getElementsByTagName('div');
console.log(box); // [<div></div>]
console.log(box[0]); // <div></div>
</script>
</body>
// 和 getElementsByClassName 一样,获取到的是一个长得像数组的元素
// 必须要用索引才能得到准确的 DOM 元素
//无论是几个,哪怕是一个,所获取到的也是一个类数组的形式
// 通过querySelector获取
//querySelector是按照选择器来获取元素的
//这个方法只能获取到一个元素,并且是页面中的第一个满足条件的元素
console.log(document.querySelector('div')) ; // 获取页面中的第一个 div 元素
console.log(document.querySelector('.box')); // 获取页面中第一个有 box 类名的元素
console.log(document.querySelector('#box')); // 获取页面中第一个 id 名为 box 的元素
// 通过querySelectorAll获取
//querySelectorAll是按照选择器的方式来获取元素
//这个方法能获取到所有满足条件的元素,组装成一个伪数组的形式返回
console.log(document.querySelectorAll('div')); // 获取页面中的所有的 div 元素
console.log(docuemnt.querySelectorAll('.box')); // 获取页面中所有有 box 类名的元素
// 获取到的是一组数据,也是需要用索引来获取到准确的每一个DOM元素
-
操作属性
-
获取元素内部的HTML结构设置元素内容(innerHTML)
-
1.获取元素内部的HTML结构
<body>
<div>
<p>
<span>hello</span>
</p>
</div>
<script>
var div = document.querySelector('div');
console.log(div.innerHTML);
/*
<p>
<span>hello</span>
</p>
*/
</script>
</body>
2.设置元素内容
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.innerHTML = '<p>hello</p>';
//设置完后,页面中的div元素里面就会嵌套一个 p 元素
</script>
</body>
-
只能获取和设置元素内部的文本内容,无法获取和设置HTML标签(innerText)
1.获取元素内部的文本内容
<body>
<div>
<p>
<span>hello</span>
</p>
</div>
<script>
var div = document.querySelector('div');
console.log(div.innerText); //hello
</script>
</body>
2.设置文本内容
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.innerText = '<p>hello</p>';
</script>
</body>
// 设置完毕以后,会把`<p>hello</p>`当做一个文本出现在div元素里面,而不会把 p 解析成标签
-
获取或修改自定义属性
1.获取属性(包括自定义属性) getAttribute
<body>
<div a="100" class="box"></div>
<script>
var div = document.querySelector('div');
console.log(div.getAttribute('a')); //100
console.log(div.getAttribute('class')); //box
</script>
</body>
2.设置属性(包括自定义属性) setAttribute
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.setAttribute('a',100);
div.setAttribute('class','box');
console.log(div); // <div a="100" class="box"></div>
</script>
</body>
3.删除指定元素的指定属性 removeAttribute
<body>
<div a="100" class="box"></div>
<script>
var div = document.querySelector('div');
div.removeAttribute('class');
console.log(div); // <div a="100"></div>
</script>
</body>
-
获取节点
-
1.节点的分类
-
DOM的节点我们一般分为常用的三大类元素节点、文本节点、属性节点
-
元素节点
-
我们通过getElementBy...获取到的都是元素节点
-
-
属性节点
-
我们通过getAttribute获取到的就是元素的属性节点
-
-
文本节点
-
我们通过innerText获取到的就是元素的文本节点
-
-
-
获取节点
获取子节点 -childNodes:获取某一个节点下 所有的子一级节点 <body> <div> <p>hello</p> </div> <script> // 这个 oDiv 获取的是页面中的 div 元素,就是一个元素节点 var oDiv = document.querySelsctor('div'); console.log(oDiv.childNodes); /* NodeList(3) [text, p, text] 0: text 1: p 2: text length: 3 __proto__: NodeList */ </script> </body> - 我们会发现,拿到以后是一个伪数组,里面有三个节点 - 一个text:从<div>一直到<p>,中间有一个换行和一队空格,这个是第一个节点,是一个文本节点 - 一个 p :这个 p 标签就是第二个节点,这个是一个元素节点 - 一个 text:从 </p> 一直到 </div> 中间有一个换行和一堆空格,这个是第三个节点,是一个文本节点 -获取父元素 -parentNode:获取某一个节点的父节点 <body> <ul> <li id="a">hello</li> <li id="b">world</li> <li id="c">!!!</li> </ul> <script> // 这个 oLi 获取的是页面中的 li 元素,就是一个元素节点 var oLi = document.querySelector('#b'); console.log(oLi.parentNode); // <ul>...</ul> </script> </body> - 只获取一个节点,不再是伪数组 - 获取的是当前这个 li 的父元素节点 - 因为这个 li 的父亲就是 ul ,所以获取到的就是 ul ,是一个元素节点 -获取其他节点 // 获取第一个子元素或者是子节点 firstChild/firstElementChild // 获取第一个子元素 获取的是回车 console.log(podiv.firstChild) // 获取第一个子节点 获取到的是标签 console.log(podiv.firstElementChild) // 所以firstChild标准浏览器会获取到空行,firstElementChild是专门解决这个问题的,但是两者不能共用 // 之所以不能同时使用,是因为浏览器不同的原因,所以说为了解决这个问题,只需要使用或者 || 就可以 // 例如 父元素.firstElementChild || 父元素.firstChild; var ul = document.getElementsByTagName("ul")[0] var ac = ul.children[2]; // 获取第一个子节点或者是子元素,并将其背景颜色设置为粉色 var one = ul.firstElementChild || ul.firstChild; one.style.background = "pink"; // 获取最后一个子节点或者是子元素,并将其背景颜色设置为绿色 var one = ul.lastElementChild || ul.lastChild; one.style.background = "green"; // 依据第三个li获取第二个li,并将其背景颜色设置为红色 var two = ac.previousElementSibling || ac.previousSibling; two.style.background = "red"; // 依据第三个li获取第四个li,并将其背景颜色设置为蓝色 var four = ac.nextElementSibling || ac.nextSibling; four.style.background = "blue";
-
操作DOM节点
-
1.建立节点
var oul = document.getElementsByTagName("ul")[0]
// 创建标签节点 li
var li = document.createElement("li")
// 创建一个文本节点
var text = document.createTextNode("这是文本节点");
var a = 1;
// 为标签节点添加内容
li.innerHTML = "你好" + a
// 将新建的文本标签放到ul里面
oul.appendChild(text)
// 将新建的li标签放到ul里面
oul.appendChild(li)
console.log(oul.childNodes)
2.插入、克隆、添加、删除等 操作DOM节点
<body>
<ul>
<li class="fz">1</li>
<li id="red">
我是用来克隆的
<span>我是span</span>
</li>
</ul>
<script>
// 先获取父元素 ul
var oul = document.getElementsByTagName("ul")[0];
// 创建一个新的li标签
var li1 = document.createElement("li");
// 并为此添加文本 为2
li1.innerHTML = "2"
// 将其插入到ul里面,成为第二个子标签
oul.appendChild(li1)
// 创建一个p标签
var p1 = document.createElement("p")
// 为p标签添加文本
p1.innerHTML = "我来插队了"
// 通过 父元素.insertBefore(newChild,refChild)方法 在refchild标签之前加入newChild节点
// 注意:参数必须是节点,添加一个已经存在的节点,会发生物理位移
// 例如 在li1标签前面添加一个p标签
oul.insertBefore(p1, li1)
// 删除当前节点
li1.remove();
// 删除父元素里面的某个子节点
oul.removeChild(p1);
// 替换节点,父元素.replaceChild(newChild,refChild)
// 将后面的节点(refChild)替换成前面的节点(newChild)
// 获取原有的第一个li节点
var li = oul.getElementsByTagName("li")[0];
var h1 = document.createElement("h1")
h1.innerHTML = "我是用来替换的"
oul.replaceChild(h1, li)
// 克隆节点
// 方法 节点.cloneNode(boolean)
// 在括号里面可以填写true和false
// 当填写true的时候代表的意思是 既有标签又有内容
// 当填写false的时候代表的意思是 复制标签,没有内容
/*
注意:
1.使用克隆复制某个标签的时候,同时也会把改标签的classname和id名也复制过来
2.也就意味着,使用该classname和id设置的css属性也同样会复制过来
3.内部的标签也会克隆过来
*/
var red = document.getElementById("red")
var hTrue = red.cloneNode(true);
var hFalse = red.cloneNode(false);
console.log(hTrue) //<h1>我是用来替换的</h1>
oul.appendChild(hTrue)
console.log(hFalse) //<h1></h1>
oul.appendChild(hFalse)
</script>
</body>
-
十、BOM
浏览器对象模型 核心是 window bom包含dom。
// 如何获取元素的可视宽,以及占位宽高
// 可视宽高 clientWidth clientHeight 元素宽度+padding
// 占位宽高 offsetWidth offsetHeight 元素宽高+padding+border
// client和offset的区别
// client的计算不包含border,offset包含border
window.onload = function () {
var div = document.getElementsByTagName("div")[0]
// client系列
// 元素.clientWidth:获取元素的可视宽 (width+左右的padding)
console.log(div.clientWidth) //520
// 元素.clientHeight:获取元素的可视高 (height+上下的padding)
console.log(div.clientHeight) //520
// 元素.clientTop:上边框
console.log(div.clientTop) //10
// 元素.clientLeft:左边框
console.log(div.clientLeft) //10
// document.documentElement.clientWidth:获取屏幕的可视宽
console.log(document.documentElement.clientWidth)
// document.documentElement.clientHeight:获取屏幕的可视高
console.log(document.documentElement.clientHeight)
// offset系列
// 元素.offsetWidth : 获取元素的占位宽(width+padding+border)
console.log(div.offsetWidth) //540
// 元素.offsetHeight : 获取元素的占位高(height+padding+border)
console.log(div.offsetHeight) //540
// 元素.offsetTop: 当前元素的顶部,到定位父元素的距离,没有定位父元素,到body的距离
console.log(div.offsetTop) //8
// 元素.offsetLeft: 当前元素的左边,到定位父元素的距离,没有定位父元素,到body的距离
console.log(div.offsetLeft) //8
}
-
十一、This 与 自定义属性
-
this
this指向的是当前元素
代码中声明了一个全局函数,是属于浏览器窗口对象的,所以this表示的就是浏览器窗口对象window
function fn() {
consolo.log(this);
}
fn()
//标签事件属性中的this指向window对象
// 如果将一个全局函数在一个标签属性中调用,如下
<button onclick="fn()">点我试试</button>
function fn() {
console.log(this)
}
//事件属性函数中的this指向当前操作的标签
// 如果在标签对象的属性上声明了一个函数,此时这个函数属于标签属性,所以函数内部的this指向当前标签对象
<button id="btn">点我试试</button>
var btn = document.getElementById('btn');
btn.onclick = function() {
console.log(this);
}
-
自定义属性
// 自定义属性:自己定义
// 固有属性:系统提供的
var oDiv = document.getElementsByTagName("div");
console.log(oDiv[0].tag); //unfined 暂时获取不到直接写在标签上的自定义属性
//1.在js中添加自定义属性 标签.属性名
oDiv[0].tag = true;
console.log(oDiv[0].tag);
-
十二、事件相关
-
绑定事件
给元素添加事件,就是绑定事件(注册事件),注册事件分为传统注册方式,监听注册方式
<body>
<button>传统注册方式</button>
<button id="jianting">监听注册方式</button>
<script>
var btn = document.querySelector('button')
var jianting = document.getElementById('jianting')
// 传统注册方式只能进行冒泡,不能进行捕获;而监听注册方式可以冒泡也可以捕获
// 传统绑定方式只能绑定一次,如果多次绑定,则会进行覆盖,只保留该元素最后一次绑定的函数
// 传统绑定事件的解绑方法,是通过元素.事件 = null;
// 监听绑定事件的解绑事件的方法,是通过在事件的内部进行解绑的
/*
监听注册事件的解绑:
(1)将解绑事件写在函数里的任何位置,其注册事件只会执行一次;
(2)将解绑事件写在函数外,那么注册的事件将无效。
(3)对于监听注册方式的解绑,需要注意事件类型和监听函数必须是相同的,否则解绑无效。
*/
btn.onclick = function () {
alert("这是传统注册方式")
// 绑定事件只发生一次,然后立刻解绑
btn.onclick = null;
}
// 监听注册方式可以给一个元素进行多次绑定
// 语法格式
// 元素.addEventListener(type, listener, useCapture);
// (1)type :必须,事件监听的类型,如 click 、 mouseover等;
// (2) listener :必须,一个实现了 EventListener 接口的对象,或者是一个函数;
// (3) useCapture :可选,表示是冒泡还是捕获。值为 true 表示捕获,否则表示冒泡 。
jianting.addEventListener('click', function () {
alert('这是监听注册方式')
})
/* jianting.addEventListener('click', function () {
alert('这是第二次监听注册方式')
}) */
// 给第二次监听进行解绑
// 1.先把里面的函数拿出来
function fn(){
alert("这是第二次监听注册方式")
// 3.将解绑事件放到函数里面
jianting.removeEventListener('click',fn)
}
// 2.将函数重新放到原来的事件里面
jianting.addEventListener('click',fn)
</script>
</body>
-
事件流
事件流包括三个阶段:事件 捕获阶段 (capture phase) 、处于 目标阶段 (target phase) 和 事件冒泡 阶段 (bubbling phase)
<script>
window.onload = function(){
// 冒泡事件,是从具体的到非具体事件的一个过程,通俗来说就是,从当前的,逐级向上
// 获取内部元素
/* var neibu = document.querySelector('.neibu')
neibu.addEventListener('click',function(){
console.log('内部')
})
// 获取外部元素
var waibu = document.querySelector('.waibu')
waibu.addEventListener('click',function(){
console.log('外部')
})
// 获取body
document.body.addEventListener('click',function(){
console.log('body')
})
// 获取html
document.documentElement.addEventListener('click',function(){
console.log('html')
})
// 获取window
document.addEventListener('click',function(){
console.log('window')
}) */
// 捕获事件 事件捕获是从不明确对象向目标对象的捕获的过程。 通俗的来讲就是从最外层一直到具体的对象
// 要想设置捕获事件,可以从只能使用事件监听注册方式,不能使用事件传统注册方式;或者是需要把监听注册方法的第三个参数设置为 true
// 获取内部元素
var neibu = document.querySelector('.neibu')
neibu.addEventListener('click',function(){
console.log('内部')
},true)
// 获取外部元素
var waibu = document.querySelector('.waibu')
waibu.addEventListener('click',function(){
console.log('外部')
},true)
// 获取body
document.body.addEventListener('click',function(){
console.log('body')
},true)
// 获取html
document.documentElement.addEventListener('click',function(){
console.log('html')
},true)
// 获取window
document.addEventListener('click',function(){
console.log('window')
},true)
}
</script>
</head>
<body>
<div class="waibu">
<div class="neibu">
内部
</div>
</div>
</body>
-
十三、ajax
-
定义
- ajax 全名 javascript and XML(异步JavaScript和XML)
- 是前后台交互的能⼒ 也就是我们客户端给服务端发送消息的⼯具,以及接受响应的⼯
- AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
- AJAX 是与服务器交换数据并更新部分网页的技术,在不重新加载整个页面的情况下。
- 是⼀个 默认异步执⾏机制的功能,AJAX分为同步(async = false)和异步(async = true)
-
什么是同步请求(false)
同步请求是指当前发出请求后,浏览器什么都不能做, 必须得等到请求完成返回数据之后,才会执行后续的代码, 相当于生活中的排队,必须等待前一个人完成自己的事物,后一个人才能接着办。 也就是说,当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面处于一个假死状态, 当这个AJAX执行完毕后才会继续运行其他代码页面解除假死状态
-
什么是异步请求(默认true,或者是不填)
默认异步:异步请求就当发出请求的同时,浏览器可以继续做任何事, Ajax发送请求并不会影响页面的加载与用户的操作,相当于是在两条线上,各走各的,互不影响。 一般默认值为true,异步。异步请求可以完全不影响用户的体验效果, 无论请求的时间长或者短,用户都在专心的操作页面的其他内容,并不会有等待的感觉。
// 1.创建一个ajax对象
var ajax = new XMLHttpRequest()
/*
2.配置链接信息
XMLHttpRequest 对象属性描述(用于和服务器交换数据。)
使用的是open方法
open的语法结构
xhr 对象中的 open ⽅法是来配置请求信息的
第⼀个参数是本次请求的请求⽅式 get / post / put / ...
第⼆个参数是本次请求的 url
第三个参数是本次请求是否异步,默认 true 表示异步,false 表示同步
xhr.open('请求⽅式', '请求地址', 是否异步)
例如:
ajax对象.open('请求方式','请求地址','本次请求是否异步[不写或者是写true以及默认均是异步处理,false是同步处理]')
*/
ajax.open('get', 'http://121.37.201.72:8082/system/film/getFilms', true);
/*
3.发送请求
通过使用send方法进行发送请求
把配置好信息的 ajax 对象发送到服务端
*/
ajax.send()
/*
这样我们就可以完成ajax的基本请求了,我们确实能把请求发送到服务端如果服务端正常的话,响应也能回到客户端 但是我们拿不到响应
如果想要拿到响应,我们需要有两个前提条件
1. 本次 HTTP 请求是成功的,也就是我们下面要说的 http 状态码为 200 ~ 299 ajax对象.status
2. ajax 对象也有自己的状态码,用来表示本次 ajax 请求中各个阶段
ajax的状态码 是用来表示一个 ajax 请求的全部过程中的某一个状态
readyState === 0 : 表示未初始化完成,也就是 open 方法还没有执行
readyState === 1 : 表示配置信息已经完成,也就是执行完 open 之后
readyState === 2 : 表示 send 方法已经执行完成
readyState === 3 : 表示正在解析响应内容
readyState === 4 : 表示响应内容已经解析完毕,可以在客户端使用了
*/
ajax.onreadystatechange = function () {
// 每次 readyState 改变的时候都会触发该事件
// 我们就在这里判断 readyState 的值是不是到 4
// 并且 http 的状态码是不是 200 ~ 299
if (ajax.readyState === 4 && ajax.status == 200) {
// 这里表示验证通过
// 我们就可以获取服务端给我们响应的内容了 接收到后端返回的JSON字符串
// 将JSON字符串转换成json对象 JSON.parse()
// console.log(JSON.parse(ajax.responseText).data.list);
// 将JSON对象转换成json字符串 JSON.stringify()
let dataList = JSON.parse(ajax.responseText).data.list;
dataList.forEach(function(item,index){
// console.log(item.filmTitle)
// document.write(item.filmTitle)
document.body.innerHTML = item.movieReview
})
}
}
-
回调函数
- 定义
-
把函数当作一个参数传到另外一个函数中,当需要用这个函数是,再回调运行()这个函数.
-
回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。(作为参数传递到另外一个函数中,这个作为参数的函数就是回调函数)
-
<script>
function add(num1, num2, callback) {
var sum = num1 + num2;
callback(sum);
}
function print(num) {
console.log(num);
}
add(1, 2, print); //3
</script>
-
ajax的原生封装
function ajax(type,url,success,data){
// type是请求方式,url是路径,success是回调函数(用来将ajax中获取到的返回值拿出来),data是传参时的参数
// 1.创建ajax对象
var xhr = new XMLHttpRequest();
// 2.建立数据链接 xhr.open(type 请求方式,url 请求数据接口地址,true 是否异步)
xhr.open(type,url,true);
// 3.发送数据请求 xhr.send()
if(data){
// 当data的有值得时候
// 请求头的设置
ajax.setRequestHeader('Content-Type', 'application/json')
// 发送
将自己的
ajax.send(JSON.stringify(data));
}else{
ajax.send()
}
// 4.状态监听
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log(xhr.response)
// 将获取到的JSON字符串装换成对象
var res = JSON.parse(xhr.response)
success(res)
}
}
}
}
-
十四、ES6语法
-
变量声明
-
let
-
// let
// 使用let进行声明变量
// 特点
// 1.不能进行变量提升
{
let a = 20;
var b = 20
}
console.log(a) //not difind
console.log(b) //20
// 2.只能作用于块级作用域里面,在外面无法打印块级里面的值
// 3.let不能重复赋值
let a = 20;
let a = 30 //这样 会报错
-
const
// 特点
// 只能声明一个常量,声明完之后不能在修改,在声明的时候就要进行初始化赋值
// 其他特点和let一样
const a = 200
a = 300 //这样就会报错,不能更改原来写的值
-
解构赋值
// 解构赋值 只能确定数组长度或者是对象的内容才能使用
// 如果数据是从后端拿来,只能使用for或者是forEach
let [a,b,c] = [5,8,9]
console.log(a,b,c) // 5 8 9
let ab = {
name:'123',
sex: "321",
num(){
console.log("猜猜我是谁");
}
}
let{name,sex,num} = ab
console.log(name,sex) //123 321
num() // 猜猜我是谁
-
元素展开
定义:元素展开 ... 针对于数组和对象的展开
-
示例
// 数组
// 用于多个数组进行组合
let a = [123,123,123]
let b = [456,456,456,...a] //可以将其放到任何一个位置上
console.log(b);
console.log(...a); //也可以进行打印时展开
// 对象 只能作用于另外一个对象当中,而无法进行打印展开
let obj1 = {
name:'123',
sex:'456'
}
let obj2 = {
num:50,
...obj1
}
console.log(obj2)
// console.log(...obj1); 会报错,无法进行展开打印
-
箭头函数
基础用法
// 基础用法
const functionName(arg1,arg2,arg3){
// 函数体
}
如果函数体只包含一个语句,你可以省略大括号并且该语句的结果会被自动返回。
// 当函数体只包含一条语句时,简写方法
const functionName = (arg1, arg2) => arg1 + arg2;
如果只有一个参数,还可以省略圆括号:
// 当仅有一个参数时的写法
const functionName = arg => arg + 5;
多参数和无参数时,不能省略小括号
// 传统匿名函数
(function (a, b) {
return a + b + 100;
});
// 箭头函数(由于有多个参数,所以括号不能省略)
(a, b) => a + b + 100;
const a = 4;
const b = 2;
// 传统无参匿名函数
(function () {
return a + b + 100;
});
// 无参箭头函数(由于无参数,所以括号不能省略)
() => a + b + 100;
注意:
函数不是直接返回表达式时,不能省略大括号和return
关键字。只有当函数直接返回表达式时,才可以省略大括号。如果函数体有额外的处理,则大括号是必需的,return 关键字也是必需的。箭头函数无法猜测函数体返回什么或何时返回。
// 传统匿名函数
(function (a, b) {
const chuck = 42;
return a + b + chuck;
});
// 箭头函数
(a, b) => {
const chuck = 42;// 进行了额外处理,不是直接返回表达式的情况,所以大括号和return不能省略
return a + b + chuck;
};
-
Promise
定义: Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,它可以获取异步操作的消息。
作用:
Promise的出现主要是解决地狱回调的问题,比如你需要结果需要请求很多个接口,这些接口的参数需要另外那个的接口返回的数据作为依赖,这样就需要我们一层嵌套一层,但是有了Promise 我们就无需嵌套,可以将嵌套结构,通过resolve和reject的调用,执行promise对象的then和catch方法,从而不再嵌套。
常用方法:
-
then方法
/**
* then方法接受两个参数:
resolve的回调函数:当状态变成resolve时会回调的函数;
reject的回调函数:当状态变成reject时会回调的函数;
*
**/
const promise = new Promise((resolve, reject) => {
})
promise.then(res => {
console.log("res:", res)
}, err => {
console.log("err:", err)
})
执行then,Promise的状态
1、当then方法中的回调函数本身在执行的时候,那么它处于pending状态;
2、当then方法中的回调函数返回一个结果时,那么它处于fulfilled状态,并且会将结果作为resolve的参数;
3、如果返回的结果是一个Promise呢?那么这个新Promise的状态会决定then返回Promise的状态;
4、当then方法抛出一个异常时,那么它处于reject状态;
promise.then(res => {
console.log("res1:", res)
// 1.直接返回一个值
return "then function fulfilled"
}).then(res => {
console.log("res2:", res)
// 2.返回Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("new promise fulfilled")
}, 2000);
})
}).then(res => {
console.log("res3:", res)
// 3.抛出一个异常
throw new Error("error message")
}).catch(err => {
console.log("err:", err.message)
})
-
catch()
.catch
方法是.then(null, rejection)
的别名,用于指定发生错误时的回调函数。 用于捕获错误。
var a = 10;
let promise = new Promise(function(resolve,reject){
// resolve 成功后调用
// reject 失败后调用
if(a == 10){
resolve("成功");
}else{
reject("失败");
}
})
// promise.then(success, fail)
promise.then(res => {
console.log(res);
},err => {
console.log(err);
})
// 捕获错误
promise.catch(err => {
console.log(err);
})
-
resolve与reject方法
-
resolve
有时需要将现有对象转为 Promise 对象,
Promise.resolve
方法就起到这个作用。
1、参数是一个 Promise 实例
如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
2、参数是一个thenable对象
thenable对象指的 是具有then方法的对象,比如下面这个对象。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
上面代码中,thenable对象的then方法执行后,对象p1的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42。
3、参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
4、不带有任何参数
Promise.resolve方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。
const p = Promise.resolve();
p.then(function () {
// ...
}); // 此时 p 就是Promise对象
-
reject()
Promise.reject(reason)
方法也会返回一个新的 Promise 实例,该实例的状态为rejected
。
注意,
Promise.reject()
方法的参数,会原封不动地作为reject
的理由,变成后续方法的参数。这一点与Promise.resolve
方法不一致。
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
// 生成一个 Promise 对象的实例p,状态为rejected,回调函数会立即执行。
const thenable = {
then(resolve, reject) {
reject('出错了');
}
};
Promise.reject(thenable)
.catch(e => {
console.log(e === thenable)
})
// true
// Promise.reject方法的参数是一个thenable对象,执行以后,后面catch方法的参数不是reject抛出的“出错了”这个字符串,而是thenable对象。
-
Promise.all()
all()方法的参数都是promise对象
执行逻辑:
Promise.all([p1,p2,p3])
把promise打包,扔到一个数组里面,打包完还是一个promise对象
如果是all方法,必须确保,所有的promise对象,都是resolve状态,都是成功的状态,否则就报错
let p1 = Promise.resolve("p1成功");
let p2 = Promise.resolve("p2成功");
let p3 = Promise.resolve("p3成功");
Promise.all([p1,p2,p3]).then(res => {
console.log(res); // 这里的res是一个有p1,p2,p3里面的resolve组成的数组
let [res1,res2,res3] = res;
console.log(res1,res2,res3);
});
// 如果p2是reject
let p1 = Promise.resolve("p1成功");
let p2 = Promise.reject("p2成功");
let p3 = Promise.resolve("p3成功");
Promise.all([p1,p2,p3]).then(res => {
console.log(res); // 这里的res是一个有p1,p2,p3里面的resolve组成的数组
let [res1,res2,res3] = res;
console.log(res1,res2,res3);
});
// 居然报错了
-
Promise.race()
Promise.race([p1,p2,p3])
这个和all用法一样,唯一不同之处就是race方法只要最前面一个resolve就可以正常执行,如果排在前面的是reject就报错
let p1 = Promise.resolve("p1成功");
let p2 = Promise.reject("p2成功");
let p3 = Promise.resolve("p3成功");
Promise.race([p1,p2,p3]).then(res => {
console.log(res); // 这里的res是一个有p1里面的第一个resolve值
});
如果全部都是reject
let p1 = Promise.reject("p1成功");
let p2 = Promise.reject("p2成功");
let p3 = Promise.resolve("p3成功");
Promise.race([p1,p2,p3]).then(res => {
console.log(res); // 因为第一个是reject,所以报错
});
示例
// 异步处理函数
function foo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(20)
}, 3000)
})
}
// 封装超时函数
function timeoutPromise(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('超时')
}, delay)
})
}
Promise.race([
foo(),
timeoutPromise(1000)
]).then(function (res) {
console.log('res', res)
}, function (err) {
console.log('err', err)
})
-
async与await
- async 的特点
- await 只能放到async函数中使用
- 相比generator 语义化更强
- await后面可以是promise对象,也可以是数字,字符串,布尔值
- async 函数返回的是一个promise对象
- 只要await 语句后面的Promise的状态变成reject,那么整个async函数会中断执行
- 注意事项
- await配合async使用
- 如果await后面的语句出错,函数后面将中断执行
- 解决报错
- 使用 try { } catch (){}
- 添加catch 捕获错误
- 统一捕获错误
1、使用 try { } catch (){}
async function fn(){
try{
await Promise.reject('出错了')
}catch(e){
let a = await Promise.resolve("成功了");
console.log(a);
}
}
2、添加catch 捕获错误
async function fn(){
await Promise.reject('出错了').catch(err=>{
console.log(err);
})
let a = await Promise.resolve("成功了");
console.log(a);
}
3、统一捕获错误
try {
let f1 = await Promise.resolve('成功了');
let f2 = await Promise.resolve('成功了');
let f3 = await Promise.reject('出错了');
}catch(e){}
4、也可以用Promise.all()方法
async function show() {
let p1 = await new Promise((res, rej) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/1',
success: function (data) {
console.log(data);
res()
},
error: function (err) {
rej()
}
})
});
let p2 = await new Promise((res, rej) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/2',
success: function (data) {
console.log(data);
res()
},
error: function (err) {
rej()
}
})
});
}
let pp = show();