JavaScript
一、变量、运算符和简单事件
1、JS文件的引入:
1.script标签中写js代码,script标签可以放在html标签中的任意位置,但是最好的位置是body尾标签之前。
2.用script标签的src引入外部的js文件。
注:如果一个script标签中已经引入了外部的js文件,那么这个script标签中,不建议再写其他的js代码。 一个页面中可以引入多个js文件。
<–JS外部引入–>
<script src="js存放路径" type="text/javascript" charset="utf-8"></script>
<–JS内部引入–>
<script type="text/javascript"></script>
1.JavaScript:
1.js(简称)
2.任务:
(1)控制页面的元素,让其实现期望效果。
(2)用户操作(键盘操作、鼠标操作)和页面之间的交互。
3.组成:
ECMAScript:JS的标准(es5)。
DOM:ducument object model 文档对象模型
BOM:browser object model 浏览器对象模型
-
var(声明变量)
-
关键词var
2.变量名称:指向电脑中某一块内存,可以根据变量名,拿到其所代表的数据。
变量名命名规则:
(1)必须由数字、字母、下划线、$构成
(2)不能以数字开头
(3)大小写敏感(区分大小写)
(4)不能使用关键词和保留字(关键词一旦出现,就代表一个特殊的含义,它会去完成它的任务,认为不是作为变量名存在)
3.最常用的三种输出方式:
(1)alert();在浏览器中弹出一个信息输出框
(2)document.write();在body标签中输出一些信息(可以输出HTML代码,任意)
(3)console.log();在控制台输出一些调试信息(浏览器输出的报错,也是console)
1.js中的数据类型
1.number(数字)
2.string(字符串)
3.boolean(布尔值)(true flase)
4.array(数组)一组数组
5.object(对象)若干对数组
6.null (空) null的数据类型是object
7.undefind(未定义)
注:null是有值,只不过值为空(在存储数据的内存上占了那一块内存,但是里面什么都没有放),undefind是只有一个变量名称,没有值(没有分配存储空间)
1.数据类型的转换
(1)显示转换
Number(),String(),Boolean()
(2)隐式转换
‘4’ < 8 ‘6’ < 4;
1.number转boolean,非0为true,0为false
字符串转boolean,非空为true,空为false
null和undefind转boolean都是false
1.运算符
1.算数运算符:
+ - * / % 自增和自减
复合运算符
+= -= *= /= %=
2.关系运算符
> < >= >=
== === != !==
==:只要值相等,就返回true(不判断类型)
!=:只判断值,值不一样,返回true(不判断类型)
!==: 值不一样或者类型不一样,才是true(判断类型)
关系运算符的运算结果是一个boolean的值
特殊情况:
(1)null
(2)两个字符串 (A,B)比较,先拿A,B的第一个字符的ASCII码比较,能比较出结果,那直接产生A,B比较的结果,比较失败,依次按顺序比较之后的字母,直到产生大小结果为止
3.逻辑运算符
&& || !
&&(与):都真为真,遇假则假
||(或):都假为假,遇真则真
!(非):非真即假,非假即真
注:
(1)&&和||的运算结果不一定是一个boolean类型的值,做运算时,先按照boolean的运算规律运算,最后将产生结果的决定数据返回。
(2)运算短路: &&:遇到一个决定false的数据短路
||:遇到一个决定true的数据短路
(3)&&的优先级比||高
4.不同类型相加
number + string = 字符串
string + 任意 = 字符串
boolean + number = 字符串
undefined + 任意 = NaN(not a number)
5.三目运算符
运算符除了可以根据运算的种类分类(比较,算数,逻辑,赋值)之外,还可以根据完成这个运算所需要的数据个数分类
单目:只需要一个数据就可以完成运算。 !(非)、++ 、 –
双目:需要两个数据。算数运算符,逻辑运算符(除!)
三目:condition ? res1 : res2;
先判断condition,为真返回res1,为假返回res2。
三目运算符相当于一个简单的if…else…判断
1.简单的点击事件
获取元素:document.getElementById('Id');
点击事件:onclick
鼠标移入、移出:onmouseover、onmouseover
二、分支语句
-
if语句
-
写法一
if(condition){
code
}
if(condition){
code
}
if语句的执行步骤:先执行condition,condition可以是一个代码执行过程,也可以是单个的任意数据,只要最终能产生一个结果,都可以。condition执行完毕之后,将结果隐式转换成boolean,true执行code,false不做反馈。
- 写法二
if(condition){
code
}else{
code
}
condition为true执行code1(不执行code2),如果condition为false,执行code2(不执行code1)
- else…if…
if(condition1){
code1
} else if(condition2){
code2
} else if(condition3){
code3
} else{
code4
}
一个if…else… if…else语句,先按照顺序判断condition,为真执行所对应的code,为假则判断下一个condition,直到这个语句结束
- switch…case…语句
switch(data){
case1 'value1':
code1
break;
case2 'value2':
code2
break;
...
default:
break;
}
(1)switch…case语句执行步骤:判断data的值:按照顺序匹配case,匹配成功,执行这个case所对应的code,switch语句执行结束,匹配失败接着匹配下一个case,如果所有的case都匹配失败,执行default(default可以省略,省略不写不影响switch语句的正确流程)
三、循环语句
- while语句
while循环:
while(condition){
code
}
(1)执行步骤:
while:循环的关键词之一
condition:条件,可以是表达式,某个具体数据。一个计算过程等,只要最终产生数据结果即可。while会自动把数据隐式转换成boolean作为循环是否需要执行的条件(true执行)。
注:
(1)循环没有结束,循环之后的代码不会执行
(2)不为循环设置结束的条件,就会形成死循环
(3)页面中不允许出现死循环
- do…while…语句
do {
code
} while(condition);
(1)执行步骤:
先执行do中的code(循环体),在判断condition(循环条件),true执行循环体代码,false循环结束,执行循环之后的代码
(2)do…while… 和while… 区别:
(1)前者先执行循环体,再判断条件,后者先判断条件,再执行循环体
(2)如果循环条件为假,do…while…循环会执行一次, while循环一次也不会执行(条件为真且条件相同时,二者没有区别)
- for
for(var i = 0; i < 10; i++){
Code
}
-
var i = 0;循环变量的初始化(声明并且赋初值)
-
i < 10; 循环条件。在循环条件的位置(第二个表达式,可以有任意数据,最终都会用这个数据boolean结果决定循环是否执行)
-
i++; 循环变量自增(自减)
-
code:循环体代码(循环条件允许,就会被重复执行)
注:
(1)循环变量的初始化可以在循环之外(不建议)
(2)循环变量的自增(自减)可以从第三个表达式的位置挪到循环体代码中(不建议)
(3)循环变量的自增(自减)不一定是1,可以是任何指定值
各个循环之间可以相互转化。一个循环需求可以使用任意的循环代码完成,只不过是代码维护和代码量略有区别
- for…for…
双层for循环执行规律:
(1)外层循环控制行,内层循环控制列
(2)外层循环的循环体执行一次,代表内层循环执行一遍(所有)
(3)可以在循环体代码中使用两个循环的循环变量
- continue
在代码有需求的地方,跳出循环:
continue:结束当次循环,让循环直接在遇到continue的位置跳到下一次,continue之后的循环体代码不再执行
break:强制结束当前循环,执行循环之后的代码
6.switch…break
switch语句在执行时,找到第一个符合条件的case,执行这个case对应的代码,如果这个case的代码中,丢失了break,那么在执行完这个case的代码后,switch会紧接着执行后一个case中的代码,如果还没有break,就继续执行,直到碰到break,停止
四、数组
1.Array
(1)实例化 new:关键词 ,从一个类别中刻画出一个数据.
var arr1 = new Array();
(2) arr2:在声明的同时确定arr1中的元素个数和具体的元素
var arr2 = new Array('hello', 3, true);
(3)字面量
var arr4 = ["name" , "sex" , "age"];
(4)length: 获取数组的元素个数
console.log(arr4.length);
(5)获取或者设置数组中的数据
document.write('<h1>' + arr4[0] + '</h1>');
2.Array_fuction
-
push:向数组的尾部添加元素
-
unshift:向数组的头部添加元素
-
pop:删除数组最后一个元素
-
shift:删除数组第一个元素
-
splice:向(从)数组中添加(删除)元素
arr.splice(index,howmany,‘item1’,‘item2’);
index :规定添加(删除)元素的位置
howmany:要删除的元素数量。0代表不删除
item:添加的元素
-
concat:arr1.concat(arr2,arr3···); 合并arr1和arr2和arr3等;产生一个新的结果。被合并的数组本身不会变色变化
-
join:以指定的字符连接数组中所有的元素,形成一个新的字符串(数组本身不会发生变化)
-
数组赋不重复值
向一个空数组中添加5个不重复的指定区间的number,区间[20 - 88],
var arr = []; // 声明一个空数组
for(var i = 0;i < 5;i++){ //for循环条件
arr[i] = Math.round(Math.random() * 68 +20); //为arr[i]赋值
if (arr.indexOf(arr[i]) != i) { //if判断:在arr中查找arr[i],如果当前赋值的下脚标不是当前的i,则i--
i--; //重新给arr[i]赋值
}
}
console.log(arr);
- 数组求最大值
过滤一个数组中的元素
//声明数组
var arr = [56, 234, 237, 47, 78, 41, 60, 72, 51];
//循环arr
var max = Math.max.apply(null,arr);
console.log(max)
- 数组去重
(1)
var arr = [1 , 2 , 4 , 5 , 6 , 1 , 5 , 2 , 8 , 10 , 9]; //声明一个数组
var arr1 = []; //再声明一个空数组用来存放arr数组不重复的元素
for (var i = 0;i < arr.length;i++) { //for循环条件
if (arr1.indexOf(arr[i]) == -1) { //if判断:arr1中如果没有arr中的元素就push进去,如果有不做任何反馈
arr1.push(arr[i]); //判断后执行语句
}
}
console.log(arr1);
(2)
var arr = []; //声明一个空数组
//循环添加
for (var i = 0;i < 5;i++) {
//生成一个指定区间的随机数
var num = Math.round(Math.random() * 12 + 6);
//判断当前这个随机数在arr中是否已经存在,如果存在,就重新生成一个
if (arr.indexOf(num) >= 0) {
//num已经在arr中存在
i--; //当前的这次循环无效,但是循环就只有3次,当前循环无效意味着数组中会少一个元素,为了避免这种情况,将循环的i值恢复。结束当前循环体的执行,执行循环的下一次(break,直接结束整个循环,执行循环后面的代码)
continue;
}
//将num添加到数组中
arr.push(num);
}
(3)
var arr = []; //声明一个空数组
//只有数组长度不是5,那就要继续生成
while(arr.length < 5){
//生成范围内的随机数
var num = Math.round(Math.random() * 12 + 6);
//判断num在arr中是否存在
if(arr.indexOf(num) < 0){
//不存在,push
arr.push(num);
}
}
- 水仙花数
//求100 - 1000水仙花数
for (var i = 100;i < 1000;i++) { //for循环条件
var a = parseInt(i % 10); //取个位数整数
var b = parseInt((i /10) % 10); //取十位数整数
var c = parseInt(i / 100); //取百位数整数
a = Math.pow(a,3);
b = Math.pow(b,3);
c = Math.pow(c,3);
if (a + b + c == i) { //if判断条件
console.log(i); //控制台打印i
}
}
五、字符串
字符串可以被循环,循环时可以拿到字符串中的每一个字符
(1)str.length 可以获取到字符串的长度(这个字符串中单个字符的数量)
(2)字符串中的单个字符在字符串中是有位置的(index下标),可以通过str[index]的方式获取到一个字符串中指定位置的字符
for (var i = 0;i < str.length;i++) {
document.write('<span>' + str[i] + '</span>');
}
(3)charAt 获取指定位置的字符
var str = 'hello world';
var res = str.charAt(10);
console.log(res);//'d'
(4)concat 连接指定的字符串,形成一个新的字符串
(5)slice 截取字符串
str.slice(index);
从str的第index个位置开始(包含这个位置),截取到字符串的末尾
str.slice(start,end);
从str的第start个位置(包含这个位置)开始,截取到第end个位置(不包含这个位置)
(6)indexOf 获取指定字符串在父级字符串中第一次出现的位置
(7)lastIndexOf 获取最后一次出现的位置
(8)replace 替换 (第一次出现)
(9)split 将字符串以指定的字符分割成一个数组
(10)substr 可在字符串中抽取从指定下标开始的指定数目的字符。
str.substr(index,length);
从str的第index个位置(包含这个位置)开始,截取length个字符
str.substr(index);
从str的第index个位置(包含这个位置)开始,截取到字符串的末尾
(11)substring 用于提取字符串中介于两个指定下标之间的字符
str.substring(start,end);
从str的第start个位置(包含这个位置)开始,截取到第end个位置(不包含这个位置)
str.substring(index);
从str的第index个位置开始,截取到字符串的末尾
(12)toUppercase 用于把字符串转换为大写
(13)toLowerCase 用于把字符串转换为小写
注:slice函数的两个参数可以为负值,负值代表字符串从右往左数的顺序,倒叙的第一个位置是-1,传负值时,要按照字符串从左往右的顺序传位置
六、数组循环和DOM元素
(1)
-
使用js方式创建元素:
document.createElement(‘tagName’);
-
将js创建的元素添加到页面中:
document.appendChild(newEle);
newEle必须是一个由js的document.createElement方式创建的元素
-
js只操作使用js方式创建的标签和使用js方式获取的标签
ele.style.background = 'red'; ele.value; ele必须是个js中的标签对象 //使用js的方式为newEle设置样式,只有这个js创建的标签被添加到html中,
//那么js代码对其做的所有操作都会实时响应在页面渲染上
//通过js为元素设置的样式是行间样式(设置在styl属性上了)
(2)//通过innerHTML方式,向box1中添加一个div
box1.innerHTML = '<div style="background: blue;"></div>';
//通过appendChild的方式,向box2中添加一个div
var newEle = document.createElement('div'); //用js方式创建一个div
(3) getComputedStyle(js的节点对象)方式获取到的样式是这个标签 最终的生效样式,某些样式有特殊的解析方式
七、函数
1.(1)封装函数的步骤:
fuction fnName(){
//code
}
-
fuction:封装一个函数的关键词
-
fnName:函数名
-
():声明这个函数封装过程中未知的一些数据
-
{ //code }:函数体(代码块)
调用函数:
1.让函数体中的代码从第一行执行到最后一行(如果一段代码只是被封装成了函数,但是却没有调用
,那么这段代码也就不会执行)
2.fnName();
fnName:找到被封装成fnName的那段代码
( ):执行代码
(2)函数封装的好处:
-
增加代码的可维护性(调试时,屏蔽某部分代码,只需要屏蔽其函数调用即可)
-
让代码的结构更清晰
-
降低代码冗余(一段非连续执行的相似代码块,如果不封装,每次实现这个功能,都要重复写一段类似的代码,不仅占用内存,代码冗余也高,如果将这些代码封装成一个函数,那么它只占用一段内存,需要执行时,调用即可)
(3)什么时候需要封装函数:
-
一个功能封装一个函数
-
重复执行的非连续的代码块(重复执行的连续的代码块用)
(4)函数的参数:
-
在封装函数时,函数体内有某些数据是未知的,那么这些未知的数据,我们在函数名后的小括号中声明。用逗号隔开,它们是这个函数的形参
-
在函数调用时,如果这个函数需要在调用函数时确定函数内代码中未知的数据(形参)的具体值,那么就要在函数调用的小括号内把具体的数据传进去,它们就是调用函数时传入的实参
在下面的例子中,声明函数的min和max就是形参,调用函数传入的43和80就是实参
注:
(1)如果声明函数时不需要使用形参,那么调用函数时也不需要传入实参
(2)函数的形参相当于在函数体中声明的变量,可以在函数体中随意使用(不能在函数体外使用)
(5)
-
函数的参数数量可以确定,也可以不确定
-
过程性的函数封装(执行一个过程):
一段代码被不断的使用,只需要从第一行执行到最后一行即可
-
结束性的函数封装(拿到一个数据):
一段代码执行完之后产生了一个结果,我们需要使用这个结果
2.变量的作用域
变量的作用域:
全局变量:在所有函数外声明的变量,可以被随意访问,设置
局部变量:在函数体内声明的变量,只能在这个函数内进行访问、设置
八、 计时器
-
setTimeout(fn,timing);
这个函数会在函数调用的timing时间之后,执行fn中的代码块
timing:number,单位为毫秒(1s = 1000ms)
setTimeout的返回值:返回当前这个计时器在浏览器运行栈中的编号
-
setInterval(fn,timing)
每隔timing时间间隔就会执行一次
函数的返回值是这个计时器在浏览器中的编号
-
clearTimeout(index); //阻止setTimeout的调用
clearInterval(index); //阻止setInterval的调用
index:要阻止调用的计时器在浏览器中的编号
九、动画
-
offsetWidth和offsetHeight获取到的元素的宽、高:
content(样式中设置的width) + 左右(上 下)padding+左右(上下)border
-
clientWidth和clientHeight获取元素的宽高:
content(style中设置的width) + 左右(上下)的padding
-
IE浏览器获取元素计算后的样式
ele.currentStyle.width;
注:offsetLeft、offsetTop、offsetWidth、offsetHeight都是只读方式,只能通过这种方式读取值,不能通过这种方式设置值
如ele.style.width;这种方式既能读取样式,也能设置样式
getCompuedStyle();也是一种只读方式
十、DOM
1.getElement
(1)getElementById() :返回带有指定ID的元素
(2)getElementsByTagName():返回包含带有指定标签名称的所有元素的节点列表(节点数组)
(3)getElementsByClassName():返回包含带有指定类名的所有元素的节点列表(节点数组)
(4)getElementsByName():根据元素的name属性值获取元素
(5)querySelector():返回文档中匹配指定CSS选择器的一个元素。
(6)querySelectorAll():返回文档中全部匹配指定CSS选择器的所有元素
2.其他获取方式
(1)nextSibling:获取下一个兄弟节点
(2) nextElementSibling:获取后一个元素兄弟节点
(3)previousSibling:获取前一个兄弟节点
(4)previousElementSibling:获取前一个元素兄弟节点
(5)lastChild:获取父级标签中最后一个子节点
(6)lastElementChild:获取父级标签中最后一个元素子节点
(7)firstChild:获取元素的第一个子节点
(8)firstElementChild:获取元素的第一个元素子节点
(9)children:获取元素所有元素子节点
(10)childNodes:获取元素的所有子节点(包含文本节点)
(11)parentNode:获取元素父级节点
3.其他操作方式
replaceChild(要替换的元素,被替换的元素);
removeChild(要删除的元素);
remove();删除本身
prepend:将元素添加到父级元素的最前方