day01
一、JavaScript:
简称js,是一个运行在浏览器端的解释型、弱类型、面向对象的脚本语言。
浏览器端:环境,自带js解释器,打开浏览器可以自动运行,以后也会安装一个独立的js解释器。
解释型:在程序运行之前,不需要检查语法是否正确,直接运行,碰到错误就停止。
编译型:在程序运行之前,需要先检查语法是否正确,如果不正确,直接不运行。
弱类型:变量保存的数据可以是任意的,数据类型由数据来决定。
强类型:变量保存的数据,由数据类型来决定。
面向对象:对象名.属性名;对象名.方法名();
二、JavaScript的特点:
- 可以使用一切编辑工具编辑代码;
- 解释型
- 弱类型
- 面向对象
- 可以做一切css完成不了的效果(轮播、选项卡、购物车、验证...)
三、引入:
- 在html页面上书写一个script标签,在里面书写代码
<script>
//js代码
</script>
- 创建一个.js文件,再在html中进行引入
<script src="xx.js">
//这里面不能写代码
</script>
四、输出方式/打桩输出:
- 在控制台输出日志:console.log(想要输出的东西),不会影响到页面
- 在页面输出日志:document.write(想要输出的东西),如果搭配上点击事件会把页面的所以东西替换掉
- 在弹出框输出日志:alert(想要输出的东西),有时候会卡住整个页面,导致用户只能看见一个白板
五、变量:
创建后可以再次修改
语法:var 变量名 = 值
变量名不是随意的:
- 不能以数字开头
- 建议驼峰命名法或下划线命名法
- 命名要尽量见名知意
- 如果变量名是name,不管你保存的数据类型是什么,都会悄悄给你转成字符串
- 变量名不能是关键字
- 声明变量不赋值结果为undefined
- 同时创建多个变量:var 变量名 = 值,变量名 = 值;
六、常量:
创建后,不允许在修改了,其余特点和变量一样
语法:const 常量名 = 值
七、数据类型分类:
- 原始/基本/值数据类型:
- number:数字,NaN,颜色为蓝色
- string:字符串,必须加上""或者'',颜色为黑色
- Boolean:布尔,取值只有true和false,颜色为蓝色
- null:空,取值只有一个就是null,作用是释放变量释放内存,节约内存空间,提升网页的性能,颜色是灰色
- undefined:只有一个取值就是undefined,颜色为灰色
- 引用/对象数据类型:11个对象
查看数据类型:typeOf(变量)
八、运算符:
- 算术运算符:+、-、*、/、%(取余)
- 算术运算符带有隐式转换,默认会把左右两边转为数字在计算
- true-->1
- false-->0
- undefined-->NaN
- null-->0
- "100"-->100
- "100px"-->NaN
- NaN:Not a Number,不是一个数字,但是它确实是数字类型,有两个缺点:
a. 参与任何的算术运算结果均为NaN
b. 参与任何的比较运算结果都为false - +运算符号如果碰上了字符串,左右两边都会悄悄的转为字符串,然后拼接
- 比较运算符:>、<、>=、<=、==、!=、===(值和数据类型都要相同)、!==
- 结果:一定是个布尔值
- 带有隐式转换:默认左右两边都会悄悄转为数字再比较大小
- 如果参与比较的左右两边都是一个字符串,则会按位PK每个字符的十六进制的unicode号(十进制ASCII码),数字0-9<大写A-Z<小写a-z<汉字。常识:汉字的第一个字:是 一 unicode号是 4e00 ascii是19968,汉字的最后一个字:是 龥 unicode号是 9fa5 ascii是40869
- NaN参与任何的比较运算结果都是false,isNaN()在接收到一个值之后,会尝试将这个值转换为数值,如果能成功转换则返回false,否则返回true;判断是否为NaN的方法:isNaN(x)
console.log(isNaN("fe"));//true console.log(isNaN(1));//false console.log(isNaN(true));//false console.log(isNaN(false));//false console.log(isNaN(null));//false console.log(isNaN(undefined));//true console.log(isNaN(" "));//false
- undefined==null结果为true,但是undefined===null结果为false
- ===和!==都不带隐式类型转换,要求值和数据类型均相同
- 结果:一定是个布尔值
- 赋值运算符:=、+=、-=、*=、/=、%=
- =:赋值:将=右边的东西,保存到=左边的变量名之中
- i=i+1 ==> i+=1
- =:赋值:将=右边的东西,保存到=左边的变量名之中
- 逻辑运算符:&&(与)、||(或)、!(非)
- &&:与(并且),全部条件都满足,结果才为true,只要一个不满足,结果就为false
- ||:或,全部条件都不满足,结果才为false,只要一个满足,结果就为true
- !:颠倒布尔值
- 自增自减运算符:++、--
- 自增:固定的每次只能+1
- 前++:先+1,再返回值
- 后++:先返回原值,再+1
var a = 2; var result = a++ + a++ + ++a + a++ + ++a + ++a; // 2 3 5 5 7 8 console.log(result);//30
- 位运算:
- 左移:m<<n,读作m左移了n位,翻译:m*2的n次方
- 右移:m>>n,读作m右移了n位,翻译:m/2的n次方
- 底数只能是2
九、用户输入框:
var 变量=prompt("提示文字");
day02
一、流程控制结构:
- 顺序结构:默认:从上向下依次执行每一句话
- 分支结构:通过条件判断,选择部分代码执行
- 循环结构:通过条件判断,选择要不要重复执行某块代码
二、分支结构
- if...else... :
- 一个条件,一件事,满足就做,不满足就不做
if(条件){ 操作; }
- 一个条件,两件事,满足就做第一件,不满足就做第二件
if(条件){ 操作; }else{ 默认操作; }
- 多个条件,多件事,满足谁,就做谁
if(条件1){ 操作1; }else if(条件2){ 操作2; }else{ 默认操作; }
- switch...case:
switch(变量/表达式){
case 值1:
操作1;
break;
case 值2:
操作2;
break;
default:
默认操作;
}
1. case在做比较的时候是不带有隐式转换的
2. default可以省略不写的,但是不推荐,如果不写,条件都不满足的情况,则什么事儿都不会发生
if 和 switch的区别:
-
switch...case:
- 优点:执行效率较高,速度快(他比较时,case做的不是范围查找,而是等值比较)
- 缺点:必须要知道最后的结果是什么才可以使用
-
if...else...:
- 优点:可以做范围判断
- 缺点:执行效率较慢,速度慢(他做的是范围查找)
建议:代码开发完过后,要做代码优化,要尽量的少用if...else...,多用switch...case和三目运算
-
三目运算:简化分支的
语法:
- 条件?操作1:默认操作; === if...else...
- 条件1?操作1:条件2?操作2:默认操作 === if...else if..else
注意:
- 默认操作不能省略,省略了会报错
- 如果操作复杂,不能使用三目运算:操作只能有一句话,如果操作有多句话还是推荐使用switch或if
页面上一切数据js获取到后都是字符串类型
三、强制(显示)数据类型转换:
- 转字符串:2种方法
- var str=x.toString();//x不能undefined和null,会报错,undefined和null不能使用.做任何操作,因为他们不是对象
- var str=String(x);//万能的,任何人都可以转为字符串,但是绝对不要手动使用,完全等效于隐式转换,还不如+""
// .toString()方法 undefined和null不能转 会报错 因为它们不是对象
var num = 11
console.log(num);
console.log(num.toString());
console.log(true);
console.log(true.toString());
console.log(undefined);
// console.log(undefined.toString());//会报错
// console.log(null.toString());//会报错
// String()方法 任何人都可以 还不如+""
console.log(String(2));
console.log(String(true));
console.log(String(null));
console.log(String(undefined));
- 转数字:3种方法
- parseInt(str/num); - parse解析 Int整型 - 专门用于将【字符串转为整数】,执行原理:从左向右依次读取转换每个字符,碰到非数字字符就停止转换,如果一来就不认识则为NaN,不认识小数点。
- parseFloat(str); - parse解析 Float浮点型 - 专门用于将【字符串转为小数】,执行原理:几乎和parseInt一致,认识第一个小数点
- Number(x);万能的,任何人都可以转为数字,但是绝对不要手动使用,完全等效于隐式转换,还不如 -0 *1 /1
// parseInt(str/num) 转整数
console.log(parseInt(20.2));//20
console.log(parseInt("20.2"));//20
console.log(parseInt("20p"));//20
console.log(parseInt("p9"));//NaN
console.log(parseInt(".5"));//NaN
// parseFloat(str) 转小数
console.log(parseFloat(20));//20
console.log(parseFloat(20.65555));//20.65555
console.log(parseFloat("2.3"));//2.3
console.log(parseFloat("2.3p"));//2.3
console.log(parseFloat("o7"));//NaN
console.log(parseFloat(".9"));//0.9
// Number(x) 万能的 不如-0 *1 /1
console.log(Number("8.2"));//8.2
console.log(Number("8.2p"));//NaN
console.log(Number(true));//1
console.log(Number(false));//0
console.log(Number(undefined));//NaN
console.log(Number(null));//0
- 转布尔:
- Boolean(x);万能的,任何人都可以转为布尔,但是绝对不要手动使用,完全等效于隐式转换,还不如 !!x
- 只有6个为false:0,"",undefined,NaN,null,false,其余全部都是true。
- 在分支或循环的条件之中,不管以后写什么,他都会悄悄的转为一个布尔值,自带此方法
console.log(Boolean(1));
// 只有以下六种情况为false 其余都为true
console.log(Boolean(0));
console.log(Boolean(""));
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(false));
console.log(Boolean(NaN));
四、案例
// 判断不同分数
var score = prompt("请输入分数:")
if (!isNaN(score)) {
if (score <= 100 && score >= 0) {
if (score >= 90) {
alert("大于等于90")
} else if (score >= 80) {
alert("大于等于80")
} else if (score >= 70) {
alert("大于等于70")
} else if (score >= 60) {
alert("大于等于60")
} else {
alert("不及格")
}
} else {
alert("请输入0-100的数字!")
}
} else {
alert("请输入数字!")
}
// 计算BMI标准体重
var weight = prompt("请输入体重:(kg)")
var height = prompt("请输入身高:(m)")
var BMI = weight/(height*height)
if (!isNaN(weight) && !isNaN(height)) {
if (BMI > 30) {
alert("肥胖")
} else if (BMI > 25) {
alert("超重")
} else if (BMI < 20) {
alert("偏廋")
} else {
alert("正常")
}
} else {
alert("恶意输入!")
}
console.log(weight);
// 计算应缴纳的税 方法一
var salary = prompt("请输入工资:")
if (!isNaN(salary)) {
var s = 0
if (salary >= 10000) {
s += (salary - 10000)*0.1
salary = 10000
}
if (salary >= 5000) {
s += (salary - 5000)*0.05
salary = 5000
}
if (salary >= 3500) {
s += (salary - 3500)*0.025
salary = 3500
}
alert("应缴纳的税为:" + s)
} else {
alert("恶意输入!")
}
// 方法二
/* if (salary >= 10000) {
s = (salary - 10000)*0.1 + (10000 - 5000)*0.05 + (5000 - 3500)*0.025
alert("应缴纳的税为:" + s)
} else if (salary >= 5000) {
s = (salary - 5000)*0.05 + (5000 - 3500)*0.025
alert("应缴纳的税为:" + s)
} else if (salary >= 3500) {
s = (salary - 3500)*0.025
alert("应缴纳的税为:" + s)
} */
// 用户输入年月,判断每月有多少天 方法一
var year = parseInt(prompt("请输入年份:"))
var month = parseInt(prompt("请输入月份:"))
/* if (!isNaN(year) && !isNaN(monyh)) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
alert("31天")
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
alert("30天")
} else if (month == 2) {
if ((year%4==0 && year%100!=0) || (year%400==0)) {
alert("29天")
} else {
alert ("28天")
}
}
} else {
alert("恶意输入!")
} */
// 方法二
switch(month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
alert("31天")
break
case 4:
case 6:
case 9:
case 11:
alert("30天")
break
case 2:
switch((year%4==0&&year%100!=0) || (year%400==0)) {
case true:
alert("29天")
break
case false:
alert("28天")
}
}
day03
一、循环结构
反复执行相同或者相似的操作
1、循环三要素:
- 循环条件:开始-结束,循环的次数
- 循环体:做的是什么操作
- 循环变量:记录当前在哪里,并且会不断的变化
二、3种循环
1、while循环
语法:
var 循环变量=几;
while(循环条件){
循环体;
循环变量变化;
}
执行原理:首先创建出循环变量,判断循环条件,如果条件满足,则做一次循环体操作,并不会退出循环,而会回头再次判断条件满不满足,如果满足,则做一次循环体操作,直到条件不满足,才会退出循环。
- 宏观上好像感觉循环是一瞬间就结束了,但是微观上循环其实是一次一次执行的
- 在不确定循环次数的时候,需要使用死循环,while(true){死循环}
- break:退出整个循环,多半都是用来搭配死循环的
- continue:退出本次循环,下一次依然会执行
2、for循环
语法:
for(var 循环变量=几;循环条件;循环变量变化){
循环体;
}
- 死循环:for(;;){}
- while和for的区别: 他们原理上几乎没有区别,一般来说我们不确定循环次数的时候,会使用while循环-死循环,如果确定循环次数的时候,会使用for循环-大部分情况都是它
3、do...while循环
语法:
var 循环变量=几;
do{
循环体;
循环变量的变化
}while(循环条件)
while和do...while的区别: 区别只看第一次,如果第一次条件都满足,那么两者没有任何区别。但是如果第一次条件不满足,那么while一次都不会执行,而do...while至少会执行一次。
三、获取随机整数公式
var r = parseInt(Math.random()*(max - min + 1) + min)
四、function的基础
1、概念
function也叫函数也叫方法,先预定好,以后可以反复使用的代码段
2、如何使用函数:2步
- 定义/创建/声明:
function 函数名(形参,...){
函数体/代码段;
}
- 调用函数:
- 在js内部写:函数名(); - 程序员写几次就会调用几次
- 在HTML上面绑定事件:
<elem onclick="函数名()"></elem> //什么元素都可以绑定事件
(1) 不带参数的函数,用于执行一些固定的操作
(2) 带参数的函数,可以根据我们传入的实参不同,做的略微不同
3、何时使用函数:
- 不希望打开页面立即执行
- 希望用户来触发,提升用户的体验感
函数是js的第一等公民
4、循环和函数的区别
- 循环:几乎是一瞬间就完成了
- 函数:需要调用后才会执行
五、案例
// 输出1000句hello 方法一:while
/* var i = 1;
while(i<=1000) {
console.log(i + "hello");
i++;
} */
// 方法二 for
for(var i = 1; i <= 1000; i++) {
console.log(i + "hello");
}
// 求1-1000所有数字和 方法一:while
/* var i = 1,
sum = 0;
while (i <= 1000) {
sum += i;
i++
}
console.log(sum); */
// 方法二:for
for(var i = 1,sum = 0; i <= 1000; i++) {
sum += i;
}
console.log(sum);
// 求1-1000所有偶数的和 方法一:while
/* var i = 1,
sum = 0;
while(i <= 1000) {
if(i % 2 == 0) {
sum += i;
}
i++;
}
console.log(sum); */
// 方法二:for
for(var i = 1,sum = 0; i <= 1000; i++) {
if (i % 2 == 0) {
sum += i;
}
}
console.log(sum);
// 猜数字小游戏1-100 方法一:while
var r = parseInt(Math.random()*(100 - 1 + 1) + 1);
var hp;
var dif = prompt("请选择难度:\n1.简单;\n2.一般;\n3.困难");
hp = dif == 1? 15 : dif == 2 ? 10 : dif == 3 ? 5 : 1
while(1) {
if (hp > 0) {
var user = parseInt(prompt("请输入您要猜的数字:目前生命值为" + hp));
if (!isNaN(user)) {
if(user > r) {
alert("大了");
hp--;
} else if (user < r) {
alert("小了");
hp--;
} else {
alert("对了");
break;
}
} else {
alert("恶意输入!")
}
} else {
alert("没有生命了");
break;
}
}
// 方法二:把while(1)改为for(;;)
// 求1/1+1/3+...+1/999的和
for(var i = 1,sum = 0; i <= 999; i+=2) {
sum += 1/i;
}
console.log(sum);
//九九乘法表
for(var j = 1; j <= 9; j++) {
for(var i = 1,str = ""; i <=j; i++) {
str += i + "*" + j + "=" + i*j + " "
}
console.log(str);
}
// 让用户输入一个年份,我们来输出这个年份之后的5个闰年
var year = prompt("请输入一个年份:");
count = 0;
while(1) {
if(count == 5){break}
year++;
if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
console.log(year);
count++;
}
}
day04
一、自定义函数
函数就是需要先定义好,以后可以反复使用的一个代码段
1.1 何时使用
不希望打开页面立即执行,以后可以反复使用,希望用户来触发
1.2 如何使用
- 创建:2种方式
- 声明方式:
function 函数名(形参列表) {
操作
return 返回值/结果
}
- 直接量方式:
var 函数名 = function(形参列表) {
操作
return 返回值/结果
}
- 调用:
函数名()
1. var 接住返回的结果 = 函数名(实参列表)
2. 其实return的本意是退出函数,但是如果return后面跟着一个数据,顺便将数据返回到函数作用域的外部,但是return只负责返回,不负责保存,所以调用函数时要自己拿个变量来接住他
3. 就算省略return,默认也有,会return一个undefined
4. 具体需不需要得到函数的结果,看你自己:如果有一天你在全局希望拿着函数的结果去做别的操作,那么记得加return
5. 前辈们提供给你的方法,大部分基本上都加了return
1.3 作用域:
- 全局作用域:
- 全局变量 和 全局函数,在页面的任何一个位置都可以使用。
- 函数作用域:
- 局部变量 和 局部函数,在【当前函数调用时,内部可用】
- 局部变量 和 局部函数,在【当前函数调用时,内部可用】
- 使用规则:
- 优先使用局部的,局部没有找全局要,全局也没有那就会报错
- 优先使用局部的,局部没有找全局要,全局也没有那就会报错
- 局部可以使用全局的,但是全局不能使用局部的 - 解决:return
1.4 全局污染:
函数中对着未声明的变量直接赋值会造成全局污染:全局本身没有这个东西,但是被函数作用域给添加上了
1.5 声明提前:
在程序正式执行之前,将var声明的变量(轻)和function声明的函数(重),都会悄悄的集中定义在当前作用域的顶部,但是赋值留在原地
- 提升var在function之前
- 声明方式创建的函数会完整的提前
- 直接量方式创建的函数不会完整提前,只有变量名部分会提前
1.6 重载:
相同的函数名,根据传入的实参的不同,自动选择对应的函数去执行,但是JS不支持,函数名如果重复了,后面的肯定会覆盖掉前面的
- 目的:
减轻我们程序员的压力,记住一个方法就可以执行很多的操作
- 解决:在【函数内部】自带一个arguments的对象(类似数组对象):不需要我们去创建 - 哪怕没有写任何形参,他也可以接受住所有实参,所以默认你看他length长度为0
- 通过下标去获取传入的某一个实参:arguments[i] - i从0开始
- 通过length去获取到底传入了几个实参:arguments.length
- 通过判断传入的实参的不同,在内部去写判断,从而变相的实现重载
二、数组的基础
数组:创建一个变量可以保存【多个数据】
数组都是线性排列,除了第一个元素,每个元素都有唯一的前驱元素
除了最后一个元素,每个元素都有唯一的后继元素
每个元素都有一个自己的位置,称之为叫做下标,下标都是从0开始的,到最大长度-1结束
2.1 创建数组:
- 直接量方式:
var arr=[];//空数组
var arr=[数据1,...];
- 构造函数方式:
var arr=new Array();//空数组
var arr=new Array(数据1,...);
2.2 获取数组之中的元素:
数组名[i]
2.3 后续添加/替换元素:
数组名[i]=新数据;
如果下标处没人则为添加,如果下标处有人则为替换
2.4 数组具有三大不限制
- 不限制元素的类型
- 不限制元素的长度
- 不限制下标越界
- 如果获取元素时,下标越界,返回的是一个undefined
- 如果添加元素时,下标越界,会得到一个稀疏数组,如果我们搭配上我们学过循环去遍历获取每个元素,那么你会得到很多很多undefined
2.5 数组中有一个唯一的属性:length
- 语法:数组名.length
- 作用:获取到数组的长度,长度是从1开始的
- 向末尾添加元素:arr[arr.length]=新数据;
- 获取数组的倒数第n个元素:arr[arr.length-n];
- 缩容:删除倒数n个元素:arr.length-=n;
2.6 遍历数组:
往往很多情况,我们不会拿出某个元素来使用,而是拿出每个元素来进行 相同 或 相似的操作 - 搭配上循环
- 固定公式:
for(var i=0;i<arr.length;i++){
arr[i];//当前次元素
}
三、案例
// 创建一个方法 传入一个实参的时候求平方 传入两个实参的时候求和
function fn() {
/* if(arguments.length == 1) {
return arguments[0]*arguments[0]
} else if(arguments.length == 2) {
return arguments[0] + arguments[1]
} */
switch(arguments.length) {
case 1:
return arguments[0]*arguments[0]
break
case 2:
return arguments[0] + arguments[1]
break
}
}
console.log(fn(2));
console.log(fn(3,3));
// 准备一个数组 获取最大值
var arr = [1,52,566,56,2,33,526,65,,2,5,88,888]
var max = arr[0]//声明一个最大值变量 假设数组第一个数字为最大值
// 遍历数组
for(var i = 0; i < arr.length; i++) {
// 把数组中的每一位和max比较 如果数组中的数字大于max 就把这个数字赋值给max
if(arr[i] > max) {
max = arr[i]
}
}
console.log(max);
// 准备一个数组 让用户输入一个字 看看数组里面有没有这个字 有就返回下标 没有返回-1
var arr = ['今','天','星','期','四']
var user = prompt("请输入一个字:目前有"+arr)
var index = -1
for(var i = 0; i < arr.length; i++) {
if(user == arr[i]) {
index = i
}
}
if(index == -1) {
alert("没找到!")
} else {
alert("找到了,下标为:"+index)
}
//去重1:用户输入到重复的了,就去掉
/* var arr = ["今","天","星","期","四"]
var user = prompt("请输入数字,目前有:"+arr)
index = -1
for(var i = 0; i < arr.length; i++) {
if(user == arr[i]) {
index = i
}
}
if(index == -1) {
alert("没找到")
}else{
for(var i = index; i < arr.length; i++) {
arr[i] = arr[i+1]
}
arr.length--
console.log(arr);
} */
//去重2:数组里面已经有很多很多重复的了
var arr = [1,2,1,55,6,2,1,2,3,6,55,9,9,8,7,55]
for(var i = 0; i < arr.length; i++) {
for(var j = i + 1; j < arr.length; j++) {
if(arr[j] == arr[i]) {
for(var k = j; k < arr.length; k++) {
arr[k] = arr[k+1]
}
arr.length--
j--
}
}
}
console.log(arr);
// 准备一个数组,录入员工名称,不断地录入,直到用户输入了exit才停止,在控制台输出看看录入哪些人
var arr = []
while(1) {
var user = prompt("请输入员工姓名:")
if(user == "exit") {break}
arr[arr.length] = user
}
console.log(arr);
day05
一、DOM
概念:(document object model)文档对象模型,专门用于操作HTML文档的,提供了一些方法给你。
二、DOM树
- 概念:DOM将我们的HTML看作了是一个倒挂的树状结构,但是树根不是html标签,而是document的对象。
- document对象:不需要我们程序员创建,由浏览器的js解释器自动创建,一个页面只有一个document树根。
- 作用:可以通过树根找到我们想要的任何一个DOM元素/节点/对象(属性和方法)
- DOM会将页面上的每个元素、属性、文本、注释等等都会被视为一个DOM元素/节点/对象。
三、查找元素
3.1 直接通过HTML的特点去查找元素
- 通过id查找元素:
var elem = document.getElementById("id值")
- 返回值:找到了返回当前找到的DOM元素,没有找到返回一个null
- 如果出现多个相同的id,只会找到第一个
- 不使用此方法,id留给后端用
- 其实根本不用查找,id直接可用
<div id="box"></div>
<script>
// 通过id去找
var div = document.getElementById('box')
var div1 = document.getElementById('box1')
console.log(div);//<div id="box"></div>
console.log(div1);//null
</script>
- 通过标签名查找元素:
var elems = document/已经找到的父元素.getElementsByTagName("标签名")
- 返回值:找到了返回一个类数组DOM集合,没找到得到空集合
- js只能直接操作DOM元素,不能操作DOM集合,解决方式是要么拿到下标要么遍历
- 不一定非要从document开始查找,如果从document去找,会找到所有元素,可以换成已经找到的某个父元素
<ul>
<li>第一个li1</li>
<li>第一个li2</li>
<li>第一个li3</li>
<li>第一个li4</li>
</ul>
<ul>
<li>第二个li1</li>
<li>第二个li2</li>
<li>第二个li3</li>
<li>第二个li4</li>
</ul>
<script>
//通过标签名查找
var ul1 = document.getElementsByTagName('ul')[0]
var lis1 = ul1.getElementsByTagName('li')
var lis = document.getElementsByTagName('li')
var as = document.getElementsByTagName('a')
console.log(lis);//HTMLCollection(8) [li, li, li, li, li, li, li, li]
console.log(as);//HTMLCollection []
console.log(lis[0]);//拿到第一个li
console.log(lis1);//HTMLCollection(4) [li, li, li, li]
console.log(lis1[0]);//拿到第一个ul里面的第一个li
</script>
- 通过class查找元素:
var elems = document/已经找到的父元素.getElementByClassName("class名")
- 返回值,找到了返回一个类数组DOM集合,没找到得到空集合
- js只能直接操作DOM元素,不能操作DOM集合,解决方式是要么拿到下标要么遍历
- 不一定非要从document开始查找,如果从document去找,会找到所有元素,可以换成已经找到的某个父元素
<p class="p">1</p>
<p class="p">2</p>
<p class="p">3</p>
<p class="p">4</p>
<p class="p">5</p>
<script>
// 通过class查找
var ps = document.getElementsByClassName('p')
var spans = document.getElementsByClassName('span')
console.log(ps);//HTMLCollection(5) [p.p, p.p, p.p, p.p, p.p]
console.log(ps[0]);//<p class="p">1</p>
console.log(spans);//HTMLCollection []
</scripe>
3.2 通过关系去获取元素:
前提条件是必须先找到一个元素才可以使用关系
- 父元素:elem.parentNode - 单个元素
- 子元素:elem.children - 集合
- 第一个子元素:elem.firstElementChild - 单个元素
- 最后一个子元素:elem.lastElementChild - 单个元素
- 前一个兄弟:elem.previousElementSibling - 单个元素
- 后一个兄弟:elem.nextElementSibling - 单个元素
<div class="box1">
<span>1</span>
<span class="s">
<b>1</b>
<b>2</b>
</span>
<span>3</span>
</div>
<script>
// 通过关系去查找元素
var s = document.getElementsByClassName('s')[0]
console.log(s);//<span class="s"></span>
console.log(s.parentNode);//找父元素 拿到的是box1 -单个元素
console.log(s.children);//找子元素 拿到的是HTMLCollection(2) [b, b]
console.log(s.firstElementChild);//找第一个子元素 拿到的是<b>1</b>
console.log(s.lastElementChild);//找到最后一个子元素 拿到的是<b>2</b>
console.log(s.previousElementSibling);//找到前一个兄弟 拿到的是<span>1</span>
console.log(s.nextElementSibling);//找到后一个兄弟 拿到的是<span>3</span>
</script
四、操作元素
前提是先找到元素,才能操作元素
```
<ul>
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第4个li</li>
<li>第5个li</li>
</ul>
<script>
var lis = document.getElementsByTagName('li')
// lis.style.color = "#fc1"//报错 Cannot set properties of undefined (setting 'color')
lis[0].style.color = "#fc1"
</script>
```
4.1 内容
- elem.innerHTML:获取和设置开始标签到结束标签之间的内容,支持识别标签的 - 双标签
- 获取:elem.innerHTML
- 设置:elem.innerHTML="新内容"
- elem.innerText:获取和设置开始标签到结束标签之间的纯文本,不识别标签的 - 双标签
- 获取:elem.innerText
- 设置:elem.innerText="新内容"
- input.value:专门获取/设置input里的内容
- 获取:input.value
- 设置:input.value="新内容
<body>
<button>点击</button>
<a href="https://www.baidu.com/">百度</a>
<script>
// 点击切换百度和京东
var btn = document.getElementsByTagName('button')[0]
var a = document.getElementsByTagName('a')[0]
btn.onclick = function() {
if(a.innerHTML == "百度") {
a.innerHTML = "京东"
a.href = "https://www.jd.com/"
} else {
a.innerHTML = "百度"
a.href = "https://www.baidu.com/"
}
}
</script>
</body>
4.2 属性
- 获取属性值:
- elem.getAttribute("属性名")
- elem.属性名 - 简化版
- 设置属性值:
- elem.setAttribute("属性名,"属性值")
- elem.属性名="属性值" - 简化版
- 简化版的缺点:
- class必须写为className - ES6(2015年)class变成了一个关键字
- 不能操作自定义属性
4.3 样式
我们使用内联样式来操作js因为:不会影响到其他样式并且优先级最高
- 获取样式:elem.style.css属性名
- 设置样式:elem.style.css属性名="css属性值"
- 特殊点:
- css属性名,有横线的地方,去掉横线,变成小驼峰命名法
- border-radius --> borderRadius
- 获取时,我们只能取到内部样式
4.4 绑定事件
elem.on事件名=function(){
操作
关键字this:
如果单个元素绑定事件,this指的就是这个元素
如果多个元素绑定事件,this指的就是当前触发事件的元素
}
一切的获取,往往都是为了判断
一切的设置,可以说是添加也可以说是修改
五、案例
<!-- 开关门效果 -->
<button id="btn" style="background-color: #df6215;">···</button>
<div id="box"></div>
<script>
btn.onclick = function() {
if(btn.style.backgroundColor == "rgb(223, 98, 21)") {
box.style.display = "block"
btn.style.backgroundColor = "#f3af84"
} else {
box.style.display = "none"
btn.style.backgroundColor = "#df6215"
}
}
</script>
<table border="1">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
</table>
<script>
// 表格隔行变色 奇数次点击奇数行变色 偶数次点击偶数行变色
var trs = document.getElementsByTagName('tr')
var j = 0//点击次数
for(var i = 0; i < trs.length; i++) {
trs[i].onclick = function() {
j++
if(j%2==0) {
for(var i = 0; i < trs.length; i++) {
trs[i].style.backgroundColor = "#fff"
if(i%2==0) {
trs[i].style.backgroundColor = "pink"
}
}
} else {
for(var i = 0; i < trs.length; i++) {
trs[i].style.backgroundColor = "#fff"
if(i%2!=0) {
trs[i].style.backgroundColor = "#fc1"
}
}
}
}
}
</script>
<!-- 选项卡 -->
<ul>
<li class="active" dy="0">家电</li>
<li dy="1">数码</li>
<li dy="2">超市</li>
<li dy="3">建材</li>
<li dy="4">维修</li>
</ul>
<div class="active">家电</div>
<div>数码</div>
<div>超市</div>
<div>建材</div>
<div>维修</div>
<script>
/* var lis = document.getElementsByTagName('li')
var divs = document.getElementsByTagName('div')
for(var i = 0; i < lis.length; i++) {
lis[i].onclick = function() {
for(var i = 0; i < lis.length; i++) {
lis[i].style.backgroundColor="#067cea"
divs[i].style.display="none"
}
this.style.backgroundColor="#9cb6f3"
var j =this.getAttribute("dy")
divs[j].style.display="block"
}
} */
var lis = document.getElementsByTagName('li')
var divs = document.getElementsByTagName('div')
for(var i = 0; i < lis.length; i++) {
lis[i].index = i//把下标保存起来
lis[i].onclick = function() {
for(var i = 0; i < lis.length; i++) {
lis[i].className=''
divs[i].className = ''
}
this.className='active'
divs[this.index].className='active'
}
}
</script>
<!-- 购物车 -->
<table>
<thead>
<tr>
<th>商品名称</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
</tr>
</thead>
<tbody>
<tr>
<td>iPhone6</td>
<td>4488</td>
<td>
<button>-</button>
<span>1</span>
<button>+</button>
</td>
<td>4488</td>
</tr>
<tr>
<td>iPhone6 plus</td>
<td>5288</td>
<td>
<button>-</button>
<span>1</span>
<button>+</button>
</td>
<td>5288</td>
</tr>
<tr>
<td>iPad Air 2</td>
<td>4288</td>
<td>
<button>-</button>
<span>1</span>
<button>+</button>
</td>
<td>4288</td>
</tr>
<tr>
<td>iPad Air 3</td>
<td>5288</td>
<td>
<button>-</button>
<span>1</span>
<button>+</button>
</td>
<td>5288</td>
</tr>
<tr>
<td>iPad Air 4</td>
<td>6288</td>
<td>
<button>-</button>
<span>1</span>
<button>+</button>
</td>
<td>6288</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">总计:</td>
<td id="total"></td>
</tr>
</tfoot>
</table>
<script>
var btns = document.getElementsByTagName('button')
for(var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
if(this.innerHTML == '+') {
subtotal(1,this)
} else {
subtotal(-1,this)
}
getTotal()
}
}
getTotal()
function subtotal(num,btns) {
if(num==1) {
var span = btns.previousElementSibling
} else {
var span = btns.nextElementSibling
}
var spanT = parseInt(span.innerHTML) + num
if(spanT > 0 ) {
span.innerHTML = spanT
}
var price = btns.parentNode.previousElementSibling
var subtotal = btns.parentNode.nextElementSibling
subtotal.innerHTML = price.innerHTML * span.innerHTML
}
function getTotal() {
var tbody = document.getElementsByTagName('tbody')[0]
var trs = tbody.getElementsByTagName('tr')
for(var i = 0,sum = 0; i < trs.length; i++) {
var subtotal = trs[i].lastElementChild
sum += parseInt(subtotal.innerHTML)
}
total.innerHTML = sum
}
</script>