起步-JavaScript
1.基础
1.1 js引进到页面的方式和细节
常用快捷键
文本注释 快捷键 ctrl+/
多行注释/**/快捷键 alt + shift + A
基本代码格式快捷键 !+ 回车或tab
格式化代码 ctrl + A + K + F
取消格式化代码 ctrl + K + F
将css引入到页面中的几种样式
-
行内样式
-
内嵌式(将css样式写在style标签块里面,放在head中)
-
外链式(只是将内嵌式中的css样式放到外面一个单独的样式文件中)
将"<link rel="stylesheet" href="要引入css的路径">" 放在head中
- 导入式
@import "css/index.css";
将js引进页面的几种方式
- 行内引入(安全性能非常低,不推荐)
<div onclick="alert('你好!');"></div>
- 内嵌式:将js代码写在script脚本块之间
<script type="text/javascript">
alert("你好");
</script>
- 外链式:将js代码写在外面文件中,通过src找到引入
注1:在外链式中,script脚本块中不可以写js代码,写了也不执行
注2:通常将js放在body中的最后面,是因为html页面时从上到下加载的,js通常是获取html标签给予动态操作效果的, 所以需要先加载html标签再加载js
<script type="text/javascript" src="js文件的路径"></script>
1.2 js中常用的四种输出方式
- alert(“内容”) 在浏览器中弹出框显示内容
- document.write(“内容”) 在页面中输出显示内容
- console.log(“内容”) 在控制台输出内容,F12打开控制台(很多网站在控制台中都放有招聘信息)
- innerHTML/innerText: 向指定元素中动态添加内容
1.3 js组成和命名规范
js组成
- 浏览器(window浏览器对象)–>文档(document文档对象)–>html–>head/body–>…
- js:是一门轻量级的脚本编程语言
- ECMAScript(4,5):定义了js里面的命名规范,变量,数据类型,基本语法,操作语句等最核心的东西
- DOM:document object model 文档对象模型
- BOM:browser object model 浏览器对象模型
js命名规范
- js中严格区分大小写
- 使用驼峰命名法。 首字母小写,其余的每个有意义的单词的首字母大写。例如:personInfo
- 可以使用数字,字母,下划线,$ (不能以数字开头)
- 不能使用关键字和保留字
关键字:在js中有特殊意义的字
保留字:未来可能成为关键字的
1.4 js中的变量和数据类型
变量
- 变量:可变的量
- js中的变量是一个抽象的概念,变量是用来存储值和代表值的
- js中定义一个变量
var 变量名=变量值;
- js中通过var可以存储任何类型的数据类型
js中的数据类型分类
- 基本数据类型:由简单的结构组成的数字(number),字符串(string),布尔(boolean),null,undefined
- 引用数据类型:结构相对复杂一些的。对象数据类型(object),函数数据类型(function)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
var name="你好";//定义一个变量name,把字符串赋值给变量
console.log(name);
var num=12;
var str="你好";
var boo=true;
var n=null;
var m=undefined;
var obj={name:"小明"};//{}对象数据类型
var ary=[1,2,3,4];//[]数组 对象数据类型
var reg=/^1\d{11}$/;//正则 对象数据类型
var fn=function(){}//函数数据类型
</script>
</body>
</html>
1.5 数据类型-number
number
- number:正数负数,0,小数,NaN
- NaN:not a number 不是一个有效数字,但属于number数据类型的
- 一个等号是赋值
- 两个等号是判断左右两边的值是否相等 例外 NaN==NaN 不等
- isNaN();检测一个值不是有效数字的命题是否成立,是有效数字返回false,否则返回true
- 如果检测的值不是number类型的,浏览器会默认的把它转换成number类型,然后再判断是否为有效数字
console.log(isNaN("123"));//首先将字符串转换成number类型
- Number()强制转换成其他的数据类型转换成number类型,字符串中一定都需要是数字才可以转换
//Number("12")==>12
//Number("123bhgwy")==>NaN
非强制数据类型转换parseInt/parseFloat
- parseInt:从左到右,一个个字符查找,把是数字的转换成有效数字,中途如果遇到一个非有效数字,就不在继续查找
- parseFloat:和上面一样,相对多识别一个小数点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
var val=Number("12px");//NaN
if(val==12){
console.log(12);
}else if(val==NaN){ //NaN==NaN 不等
console.log(NaN);
}else{
console.log("以上都不成立");
}
//输出 以上都不成立
</script>
<!--
parseInt("12px")==>12
parseInt("12px12")==>12
parseInt("hello20")==>NaN
parseInt("12.5xbs")==>12
parseFloat("12.5xhs")==>12.5
Number("12.5siwhq")==>NaN
Number("12.4")==>12.4
-->
</body>
</html>
1.6 数据类型-boolean和数据类型转换规律
boolean
- boolean:true false
- ! -->一个叹号是取反,首先将值转换为布尔类型的,然后再取反
- !! -->将其他的数据类型转换成boolean类型,相当于Boolean()
console.log(Boolean("xiaoming"));//true
console.log(!!"xiaoming");//true
数据类型转换的规则
- 如果只有一个值,判断这个值是真还是假,只有 0,NaN,"",null,undefined这五个是假,其余都是真
console.log(!3);------>先把3转换为boolean,然后再取反
- 如果是两个值比较是否相等,遵循这个规则: val1= =val2两个值可能不是同一个数据类型的,如果是= =比较的话,会进行默认的数据类型转换
(1)对象= =对象 永远不相等
(2)对象= =字符串 先将对象转换为字符串(调用toString的方法),然后再进行比较,,[]转换为字符串为 “”,{}转换为字符串为 “[object object]”
(3)对象= =布尔类型 对象先转换为字符串(toString),然后再转换为数字(number)。 布尔类型也转换为数字(true是1,false是0),最后让两个数字比较
(4)对象= =数字 对象先转换为字符串(toString),然后再转换为数字(number)
(5)数字= =布尔 布尔转换为数字
(6)数字= =字符串 字符串转换为数字
(7)字符串= =布尔 都转换为数字
(8)null= =undefined 结果是true
(9)null或者undefined 和其他任何数据类型比较都不相等 - 在js中,除了= =是比较,= = =也是比较(绝对比较,比较数值和数据类型)
例如:null===undefined 结果是false
1.7 数据类型-object
对象数据类型
-
js数据类型中的对象数据类型,由多组【属性名和属性值】组成,多组键值对组成,由多个key:value
-
属性名和属性值是用来描述这个对象特征的
-
对象数据类型中,可以具体分为:
对象类(Object),数组类(Array),正则类(RegExp),时间类(Date),字符串类(String),布尔类(Boolean),数学函数。。等对应的实例:对象{},数组[],正则/^$/,时间。。。 -
js中的对象,类,实例的区别:
对象泛指,js中万物皆对象,类是对象的具体的部分,实例是类中的一个具体的事物
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
var obj={name:"xiaohua",age:6};
var personInfo={
name:"小明",
age:18,
height:"180cm",
weight:"60kg"
};
*/
//字面量创建方式
var obj={name:"lihua"};
//实例创建的方式
var obj=new Object();
//给一个对象增加一组属性名和属性值
obj.name="lihua";//或 obj["name"]="lihua";
//修改原有属性名的属性值,规定一个对象中的属性名不能重复,如果之前有就是修改,没有就是添加
obj.name="xiaozhang";//或 obj["name"]="xiaozhang";
//获取属性名和属性值,如果属性名不存在,默认返回的结果是undefined
console.log(obj.name);//或 console.log(obj["name"]);
//删除属性名和属性值
obj.name=null;//假删除
delete obj.age;//真删除
</script>
</body>
</html>
1.8 数据类型区分和数据类型检测
js中的数据类型分类
- 基本数据类型:由简单的结构组成的数字(number),字符串(string),布尔(boolean),null,undefined
- 引用数据类型:结构相对复杂一些的对象数据类型(object),函数数据类型(function)。对象数据类型如 [],{},/^$/
基本数据类型和引用数据类型的区别
-
基本数据类型是把值直接给变量,在接下来的操作中,两个值不影响
-
引用数据类型:
(1)定义一个变量
(2)开辟一个新的空间,然后把属性名和属性值保存在这个空间,并且有一个空间地址
(3)把空间的地址给了这个变量,变量并没有存储这个数值,而是存储了这个空间的引用地址
(4)操作的是同一个空间地址所存储的值,则其中一个改变,另一个也会改变 -
基本数据类型操作的是值,而引用数据类型操作的是对新空间的引用地址
js中检测数据类型的方式
-
typeof运算符
(1)返回值:是一个字符串,包含了数据类型字符:“number”,“string”,“boolean”,“undefined”,“object”,“function”
(2)typeof null的结果是"object"
(3)typeof的局限性:不能具体检查object下的细分类型,检查这些范围的都是"object" -
instanceof运算符
-
constructor
-
Object.prototype.toString.call()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
//基本数据类型
var num1 = 12;
var num2 = num1;
num2++;
console.log(num1);//结果为 12
//引用数据类型
var obj1 = {name:"xiaoming"};
var obj2 = obj1;
obj2.name = "zhangsan";
console.log(obj1.name);//结果为 zhangsan
console.log(typeof "xiaoming");// 显示结果为"string"
console.log(typeof(typeof(typeof(typeof []))));//出现两个及两个以上的typeof的时候,最终结果都是string
//typeof [] ===> "object"
//typeof "object" ===> "string"
//typeof "string" ===> "string"
</script>
</body>
</html>
1.9 页面中常用的几种输出方式
javascript中常用的几种输出方式
【1】在浏览器中的控制台输出,浏览器F12打开控制台.
- console.log(“要输出的内容”);
- console.dir(""); 在控制台输出一个对象的详细信息
- console.table(); 把一个数据(json)按照一个表格的形式输出,在查看结构的时候更加清晰
例如谷歌浏览器:
(1)Elements:页面中的元素都在里面,我们经常用这个来调试样式(在火狐浏览器中需要安装fireBug插件才可以实现)
(2)Network:包含了所有的资源文件(css,js外链文件,html页面,所有的图片,向后台请求的数据接口等)
还有每个文件加载完成的时间,对于时间过长的可进行相关的优化
(3)Sources:包含了项目中的html,css,js所有的源代码,扒一个网站在这里可以找到所有的源码
(4)Resources:当前网站本地存储的数据都在这里
(5)Console:页面中在控制台输出的内容就在这里
(6)有一个小手机的图片,单击后进入手机端模拟器,以后的移动端开发就是在模拟器里面完成的
(7)小手机左侧的图片,单击后再点击页面中的某部分,会自动定位到相应的样式代码
(8)可以在控制台加断点进行页面bug调试
【2】给页面中等的某个元素添加内容 innerText/innerHTML
innerText和innerHTML的区别:
(1)火狐浏览器中不支持innerText,而innerHTML不存在浏览器兼容问题
(2)innerHTML不仅可以添加文字,还可以添加html标签,而innerText不能识别有效的html标签,会把html也当做文字添加进去
var oDiv=document.getElementById("div1");
oDiv.innerText="你好";
//oDiv.innerHTML="你好";
var oDiv2=document.getElementById("div");
oDiv2.innerHTML=<a href='http://www.baidu.cn/'>可点击此处文字进入网址</a>;
【3】在页面中弹出对应的框显示内容
- alert(“要输出的内容”); 在浏览器中弹出一个框(把要输出的内容先转换成字符串,然后再输出)
- confirm(); 浏览器中确认选择弹出框(含有确认和取消的对话框),当选择"确定"时,方法返回true,点击的是取消,返回的是false,根据返回值进行对应得操作即可
【4】在页面中输出内容
- document.write();如果要在页面中添加一个广告,用这个来添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body,div{
margin: 0;
padding: 0;
}
.text{
width: 100px;
height: 100px;
border: 1px solid red;
line-height: 100px;
text-align: center;
background: aqua;
margin: 0 auto;
}
/*
margin:0 auto;水平居中 */
</style>
</head>
<body>
<div class="text" id="div1"></div>
<script type="text/javascript">
var oDiv1=document.getElementById("div1");
oDiv1.innerText="你好";
// oDiv1.innerHTML="你好";
// var oDiv2=document.getElementById("div");
//oDiv2.innerHTML=<a href='http://www.baidu.cn/'>可点击此处文字进去网址</a>;
</script>
</body>
</html>
1.10 js中三个判断的语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
三个判断:if else,三元运算符,switch case
*/
var num = 10;
if (num < 0) {
console.log("负数");
} else if (num >= 0 && num <= 10) {
console.log("0-10之间");
} else (num > 10) {
console.log("10以上");
}
//三元运算符
var num = 12;
if (num >= 0) {
console.log("正数或0");
} else {
console.log("负数");
}
//等同于num>=0?console.log("正数或0"):console.log("负数");
if (num >= 0) {
console.log("正数或0");
}
//等同于num>=0?console.log("正数或0"):void 0; 此处void 0没有意义,相当于空,用于补齐三元运算
var num = 10;
if (num == 0) {
console.log("0");
} else if (num == 5) {
console.log("5");
} else if (num == 10) {
console.log("10");
} else {
console.log("NaN");
}
/* 等同于
var num = 10;
switch (num) {
case 0:
console.log("0");
break;
case 5:
console.log("5");
break;
case 10:
console.log("10");
default:
console.log("NaN");
}
注:每一种case情况相当于===的比较,比较的时候一定要注意数据类型是否一致
*/
</script>
</body>
</html>
1.11 js中判断的应用(开关灯)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
/*
//浏览器自带
margin:0;
padding: 0;
//使整个body属于可点击状态
cursor: pointer;
*/
</style>
</head>
<body id="bodyEle" style="background-color: white;">
<script type="text/javascript">
/*
1.首先获取body
document.getElementById("元素标签的ID值")
document 文档 称之为上下文(context限定获取元素的范围)
get 获取
Element 一个元素
By 通过
Id 元素的ID
在整个文档中,通过元素的ID获取一个元素
2.让body有一个可以点击的功能
元素.οnclick=function(){}
3.点击的时候执行换颜色操作
每一次点击的时候,都要获取当前的背景颜色,根据颜色让背景变成其他颜色
元素.style.backgroundColor 获取当前元素在“行内样式”上的背景颜色
*/
//1.首先获取body
var oBody = document.getElementById("bodyEle");
//2.让body有一个可以点击的功能
oBody.onclick = function () {
var bg = oBody.style.backgroundColor;
// var bg=this.style.backgroundColor;
//在绑定的时间中,this就是当前点击的这个元素的oBody
/*
//白色和黑色通过点击换颜色
if(bg==="white"){
oBody.style.backgroundColor="black";
}else{
oBody.style.backgroundColor="white";
}
//等同于
bg === "whrite" ? this.style.backgroundColor = "back" : this.style.backgroundColor = "white";
*/
//3.点击的时候执行换颜色操作
switch (bg) {
case "white":
this.style.backgroundColor = "blue";
break;
case "blue":
this.style.backgroundColor = "red";
break;
case "red":
this.style.backgroundColor = "yellow";
break;
case "yellow":
this.style.backgroundColor = "green";
break;
default:
this.style.backgroundColor = "white";
}
}
</script>
</body>
</html>
1.12 js中三个循环之for循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
1.设置初始值 var i=0;
2.设置循环执行的条件
3.执行循环体中的内容
4.每一轮循环完成后都执行i++累加操作
*/
for(var i=0;i<10;i++){
console.log(i);
}
/*
break/continue:
在循环体中遇到这两个关键字,循环体中后面的代码就不再执行了
(1)在循环体中出现break,整个循环直接结束,i++累加操作不再执行
(2)在循环体中出现continue,当前这一轮的循环就结束,继续下一轮的循环,i++累加操作继续执行
*/
for(var j=0;j<10;j++){
continue;
console.log(j);//不执行
}
//例题
for(var m=0;m<10;m++){
if(m<=5){
m+=2;
continue;
}
m+=3;
break;
console.log(m);
}
console.log(m);
//最终输出 9
</script>
</body>
</html>
1.13 js中三个循环之for in循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
for in循环:用来循环一个对象中的属性名和属性值
*/
var obj={
name:"小明",
age:19,
height:"180cm",
hobby:"打篮球",
birthday:"99-10-27",
1:923478
};
//对象中有多少组键值对,就循环多少次
//顺序问题:首先循环数字的属性名(按照从小到大),再把剩下的属性名按照写的顺序循环
for(var key in obj){
// console.log(key);//每一次循环获取的属性名
console.log(obj[key]);//获取属性值, 在for in中通过 对象名[key]来获取 不能写obj.key
}
</script>
</body>
</html>
1.14 js中循环的应用[隔行变色+鼠标滑过变色]
通过js实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body,
div,
ul,
li {
margin: 0;
padding: 0;
font-family: Arial;
font-size: 14px;
}
ul,
li {
list-style: none;
}
#list {
margin: 10px auto 0;
padding: 10px;
width: 500px;
border: 1px solid #ddd;
border-radius: 10px;
}
#list li {
height: 30px;
line-height: 30px;
cursor: pointer;
}
.c1 {
background: turquoise;
}
.c2 {
background: violet;
}
.c3 {
background: tomato;
}
/*
//清除默认样式
ul,li {
list-style: none;
}
//边框样式为圆角
#list {
border-radius: 10px;
}
//list中的li设置为鼠标可点击状态
#list li {
cursor: pointer;
}
*/
</style>
</head>
<body>
<div id="list">
<ul>
<li>生活如海,宽容作舟,泛舟于海,方知海之宽阔</li>
<li>生活如山,宽容为径,循径登山,方知山之高大</li>
<li>生活如歌,宽容是曲,和曲而歌,方知歌之动听</li>
<li>风帆,不挂在桅杆上,是一块无用的布</li>
<li>桅杆,不挂上风帆,是一根平常的柱</li>
<li>理想,不付诸行动是虚无缥缈的雾</li>
<li>行动,而没有理想,是徒走没有尽头的路</li>
</ul>
</div>
<script type="text/javascript">
/*
原理:
操作所有的li,按照奇偶行的规律改变class样式的属性值,
奇数行是c1,偶数行是c2
通过元素标签名获取一组元素
document.getElementByTagName("元素的标签名");
在整个文档中(获取的范围,上下文),
通过元素的标签名(div,li,p.....)来获取一组元素
*/
/*
获取整个文档中所有的li,是一个集合,
叫做类数组(类似于数组),
并且类数组是对象数据类型的(object)
var oLis=document.getElementByIdTagName("li");
console.log(oLis[0]);
获取某一个指定的元素oLis[索引]
console.log(oLis.item(0));
通过DOM方法获取的类数组还可以用 .item(索引) 来获取某一个
*/
var oList = document.getElementById("list");
var oLis = oList.getElementsByTagName("li");
for (var i = 0; i < oLis.length; i++) {
var oLi = oLis[i];
//每一次循环的时候在类数组中把对应的li取出来
//oLi.className="c1";设置每一个li的class样式属性的值
//因为每一个li都是对象数据类型的,
//应用这个思想,给每一个Li增加一个自定义的属性名(color),
//属性值就是当前li的className的值
i % 2 === 0 ? (oLi.className = "c1", oLi.color = "c1") : (oLi.className = "c2", oLi.color = "c2");
//鼠标移在列表上会变颜色,移开会变成原来的颜色
oLi.onmouseover = function () {
this.className = "c3";
}
oLi.onmouseout = function () {
//先获取之前的颜色,相当于用自定义属性名oLi.color = "c1"作为之前的标记
var oldVal = this.color;
//鼠标滑过再将之前的属性值赋给现在的属性值
this.className = oldVal;
}
}
</script>
</body>
</html>
直接设置样式实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body,
div,
ul,
li {
margin: 0;
padding: 0;
font-family: Arial;
font-size: 14px;
}
ul,
li {
list-style: none;
}
#list {
margin: 10px auto 0;
padding: 10px;
width: 500px;
border: 1px solid #ddd;
border-radius: 10px;
}
#list li {
height: 30px;
line-height: 30px;
cursor: pointer;
}
/* 鼠标滑过变色也可直接通过伪类进行设置 */
#list li:hover {
background: tomato;
}
.c1 {
background: turquoise;
}
.c2 {
background: violet;
}
</style>
</head>
<body>
<div id="list">
<ul>
<li>生活如海,宽容作舟,泛舟于海,方知海之宽阔</li>
<li>生活如山,宽容为径,循径登山,方知山之高大</li>
<li>生活如歌,宽容是曲,和曲而歌,方知歌之动听</li>
<li>风帆,不挂在桅杆上,是一块无用的布</li>
<li>桅杆,不挂上风帆,是一根平常的柱</li>
<li>理想,不付诸行动是虚无缥缈的雾</li>
<li>行动,而没有理想,是徒走没有尽头的路</li>
</ul>
</div>
<script type="text/javascript">
var oList = document.getElementById("list");
var oLis = oList.getElementsByTagName("li");
for (var i = 0; i < oLis.length; i++) {
var oLi = oLis[i];
i % 2 === 0 ? oLi.className = "c1" : oLi.className = "c2";
}
</script>
</body>
</html>
1.15 综合案例-选项卡
1-15综合案例选项卡.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css/1-15综合案例选项卡.css">
</head>
<body>
<div id="tab">
<ul>
<li class="select">视频</li>
<li>综艺</li>
<li>秒拍</li>
</ul>
<div class="select">视频内容</div>
<div>综艺内容</div>
<div>秒拍内容</div>
</div>
<script type="text/javascript" src="js/1-15综合案例选项卡.js"></script>
</body>
</html>
1-15综合案例选项卡.css
body,div,ul,li{
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
}
ul,li{
list-style: none;
}
#tab{
margin: 10px auto 0;
width: 500px;
}
#tab ul{
position: relative;
top:1px;
z-index: 100;
}
#tab ul li{
float: left;
margin-right: 10px;
width: 100px;
height: 30px;
line-height: 30px;
text-align: center;
border: 1px solid #ddd;
cursor: pointer;
}
#tab ul li.select{
background: turquoise;
}
#tab div{
display: none;
clear: both;
height: 100px;
line-height: 100px;
text-align: center;
border: 1px solid #ddd;
}
#tab div.select{
display: block;
}
/*
清除默认样式
body,div,ul,li{
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
}
ul,li{
list-style: none;
}
左浮动,把几个浮动的元素放到一起,如果有空间的话,它们将彼此相邻。
#tab ul li{
float: left;
}
元素浮动之后,周围的元素会重新排列,为了避免这种情况,使用 clear 属性。
clear 属性指定元素两侧不能出现浮动元素
#tab div{
clear: both;
}
此元素不被显示(div的块级元素)
#tab div{
display: none;
}
此元素选中后显示为块级元素
#tab div.select{
display: block;
}
生成相对定位的元素,相对于其正常位置进行定位。
因此,"top:1px" 会向元素的top位置添加1像素
#tab ul{
position: relative;
top:1px;
}
*/
1-15综合案例选项卡.js
/*
第一步:分析思路
选项卡思路:鼠标滑到某一个li上面,先让所有的li个div都没有select样式,
然后再让当前的有这个select样式
*/
//第二步:要操作谁就先获取谁
var oTab = document.getElementById("tab");
var oLis = oTab.getElementsByTagName("li");
var oDivs = oTab.getElementsByTagName("div");
//第三步:制定一个功能方法,实现需求
//nIndex是定义的形参,代表当前被选中元素的索引
function tabChange(nIndex){
for(var i=0;i<oLis.length;i++){
//让所有的li和div都为空
oLis[i].className="";
oDivs[i].className="";
}
oLis[nIndex].className="select";
oDivs[nIndex].className="select";
}
//第四步:给li绑定鼠标移上去的事件
//js加载完成后(for循环加载完成 i=3),才手动触发onmouseover事件
for(var i=0;i<oLis.length;i++){
oLis[i].onmouseover=function(){
tabChange(i);
}
}
for(var i=0;i<oLis.length;i++){
//在每一次循环的时候,首先把每一个li的索引定义在自己的自定义属性click上
oLis[i].click=i;
oLis[i].onmouseover=function(){
//this是指绑定的元素
tabChange(this.click);
}
}
/*
优化代码:
var oTab = document.getElementById("tab");
var oLis = oTab.getElementsByTagName("li");
var oDivs = oTab.getElementsByTagName("div");
for(var i=0;i<oLis.length;i++){
var oLi=oLis[i];
oLi.click=i;
oLis[i].οnmοuseοver=function(){
for(var j=0;j<oLis.length;j++){
oLis[j].className="";
oDivs[j].className="";
}
this.className="select";
oDivs[this.click].className="select";
}
}
*/
1.16 综合案例-99乘法表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body,
div,
ul,
li,
span {
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
}
ul,
li {
list-style: none;
}
#tab {
position: absolute;
top: 50%;
left: 50%;
margin-left: -460px;
margin-top: -145px;
padding: 10px;
width: 900px;
height: 270px;
border: 1px solid red;
border-radius: 10px;
}
#tab li {
height: 30px;
line-height: 30px;
}
#tab li span {
display: inline-block;
width: 100px;
height: 30px;
text-align: center;
}
.c1 {
background: rosybrown;
}
.c2 {
background: rgb(52, 221, 193);
}
.c3 {
background: yellow;
}
</style>
/*
清除默认样式
body,div,ul,li,span{
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
}
ul,li{
list-style: none;
}
(1)让整体tab处于屏幕正中间,margin-left为(padding*2+width)/2
(2)absolute,生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
(3)元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定
#tab{
position: absolute;
top: 50%;
left: 50%;
margin-left: -460px;
margin-top: -145px;
padding: 10px;
width: 900px;
height: 270px;
border: 1px solid red;
}
display: inline-block清除行内块元素的样式,否则text-align: center;无效果
#tab li span{
display: inline-block;
width: 100px;
height: 30px;
text-align: center;
}
*/
</head>
<body>
<div id="tab">
/* <ul>
<li class="c1">
<span>1*1=1</span>
</li>
<li class="c2">
<span>1*2=2</span>
<span>2*2=4</span>
</li>
<li class="c3">
<span>1*3=3</span>
<span>2*3=6</span>
<span>3*3=9</span>
</li>
</ul>
*/
</div>
<script type="text/javascript">
var oTab = document.getElementById("tab");
var str = "";
str += "<ul>";
/*
字符拼接的黄金法则:
(1)单双不能同时用,外面是双,里面就是单,外面是单,里面就是双
(2)如果一个字符串中需要增加一个变量,看最外面是双还是单,如果是双,就直接“+变量+”,如果是单,则' "+变量+" '
*/
for (var i = 1; i <= 9; i++) {//行
var val = "c1";
switch (i % 3) {
case 0:
val = "c1";
break;
case 1:
val = "c2";
break;
default:
val = "c3";
}
str += " <li class='" + val + "'>";
for (var j = 1; j <= i; j++) {//列
str += "<span>";
str += "" + j + " * " + i + " = " + (j * i) + "";
str += "</span>";
}
str += "</li>";
}
str += "</ul>";
//innerHTML向指定元素中添加内容(可以是文字,也可以是html标签,innerHTML可以识别html标签)
//innerText不能识别html标签
oTab.innerHTML = str;
</script>
</body>
</html>
2.函数
2.1 基础知识
- function:函数->具备某个功能的一个方法,方法本身是没有意义的,只有执行这个方法实现对应的功能的时候才有自己的价值
- 函数有两个部分组成:创建一个函数,执行这个函数
1.创建函数:
(1)首先开辟一个新的内存空间,浏览器为其分配一个16进制的地址,假设地址为:xxxfff000
(2)把函数体中的js代码当做"字符串"存储到内存空间中
(3)把这个地址赋值给当前的函数名sum >>>>sum=xxxfff000
2. 函数执行:
(1)首先会提供一个供函数体中的代码执行的环境 -> “私有作用域”。
(2)形成的那个私有的作用域把函数体中的代码都包起来了,保护了里面的私有变量不受外界的干扰(外面获取不到也修改不了) ->把函数执行的时候形成的这种保护机制叫做“闭包”
(3)把函数体中的代码字符串变成代码从上到下执行
(4)函数执行的目的:把函数之前存储的那些字符串变成js代码,然后再让js代码从上到下依次执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
//创建一个函数
function 方法名(){
//函数体:存放的是某个功能实现的js代码
}
//执行这个函数
//创建一个函数可以执行多次,一般情况下,每次执行函数和上一次执行没有任何关系
方法名();
*/
function sum(){
var total=null;
total=1+1;
console.log(total);
}
sum();//加小括号,代表执行当前函数
sum;//不加小括号,代表的就是当前函数本身。
</script>
</body>
</html>
2.2 形参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function sum(num1, num2) {
//num1,num2就是设定的形参“变量”,他就是当前函数的两个入口
var total = null;
total = num1 + num2;
console.log(total);
}
sum(100,200);//num1=100 num2=200
sum(10);//num1=10 num2=undefined
//定义了形参,执行的时候如果没有传递值,默认形参的值是undefined
</script>
</body>
</html>
2.3 arguments
对于任意几个数的求和,就需要用到arguments
1.arguments:函数天生自带的(不管写没写形参,也不管是否传递值,arguments始终都是存在的),用来接收函数传递进来的参数值的一个集合,用来接收函数传递进来的参数值的一个集合
2.arguments是一个对象数据类型的值
3.arguments是以数字类型作为索引,索引从0开始逐级递增,索引0存储的是第一个参数值,索引n存储的是第n+1个参数值
4.arguments是一个类数组,但不是数组
5.arguments还有一个自己特殊的属性callee,代表当前函数本身
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function sum() {
var total = null;
for (var i = 0; i < arguments.length; i++) {
//把传递进来的值转换成number类型的
var cur = Number(arguments[i]);
//对于非有效数字,不再进行累加,防止最后结果是NaN
if (!isNaN(cur)) {//!isNaN(cur)=true 说明cur是有效数字
total += cur;
}
}
return total;
}
var total1 = sum(100, 200);
console.log(total1);//300
//cosole.log(sum(100,200));
console.log(sum(100, 200, 300, 400));//1000
console.log(sum());//null
console.log(sum(10, 20, "30"));//60
//未转换为number类型前,结果为3030。转换后结果为60
console.log(sum(10, 20, "30", "xiaohua"));//60
</script>
</body>
</html>
2.4 return
闭包
<script type="text/javascript">
function sum(num1,num2){
var total=null;
total=num1+num2;
}
sum(100,200);
console.log(total);//Uncaught ReferenceError: total is not defined
/*total这个变量没有定义==》函数执行的时候,
首先会形成一个私有的作用域,保护里面的内容不受外界的干扰(闭包),
导致了在函数体中给定义的变量total,在函数体的外面不能直接的获取到
*/
</script>
return第一个作用:返回值机制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function sum(num1,num2){
var total=null;
total=num1+num2;
return total;
/*return就是当前函数提供的出口,
因为不提供出口的话,闭包的机制导致了再函数体的外面无法获取里面total的值,
如果想在外面用total的值,只需要通过return 把total的值返回给外面即可==》"返回值机制"
*/
}
var total= sum(100,200);
/*
1.首先把函数sum执行,然后把sum执行的返回值赋值给total
2.看sum执行的返回结果,只需要看sum中是否存在return,有return,其后面返回的值是什么,那么函数的返回值就是什么
3.如果sum中没有return,那么默认的返回值是undefined
*/
console.log(total);
</script>
</body>
</html>
return第二个作用:终止函数体中代码的作用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function fn() {
var total = 2;
return;//在函数体中return下面的代码都不会执行了==>"终止函数体中代码的作用"
console.log(1);//不执行
}
console.log(fn);//输出当前函数本身
console.log(fn());//函数体没有return或者return后没有值,则最后打印都为undefined
</script>
</body>
</html>
2.5 匿名函数
- 实名函数:起了名字的函数就是实名函数
- 匿名函数:没有起名字的函数就是匿名函数
在js中常用到的匿名函数有两种方式:
(1)自执行函数:定义函数和函数执行一起完成了
;(function(num){
})(100);
//前面加分号的作用是为了防止上面代码结束不加
以下几种写法都可:
+function(num){}(100);
-function(num){}(100);
!function(num){}(100);
~function(num){}(100);
(2)函数表达式:把函数定义的部分当做一个值赋值给一个变量或者元素的某一个行为
oDiv.onclick=function(){}
3.数组和算法
3.1 数组基础知识
- object -> {},[],/^$/,时间
- 每一个对象都是由属性名和属性值组成的
- 数组也是对象,看到的是它的属性值,属性名是数字
- length属性是浏览器天生就给数组增加的(不是自己编的属性),这个属性属于当前数组不可枚举的属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
var ary = [12, 23, 34, 45];
console.dir(ary);
for(var i=0;i<ary.length;i++){
console.log(ary[i]);
}
//也可用for in来遍历
/*for in循环是用来遍历一个对象中属性名和属性值的,
但是对于当前对象不可枚举的属性通过它是遍历不到的
例如:无法遍历到ary.length这个属性
*/
for(var key in ary){
console.log(ary[key]);
}
</script>
</body>
</html>`
3.2 数组常用的15个方法
学习数组需要注意的四点:
(1)方法的作用
(2)需要传哪些参数
(3)是否有返回值,返回值是什么
(4)通过此方法是否对原来的数组产生了改变
(5)是否兼容所有的浏览器
1.关于数组的增删改查
(1)push:向数组的末尾增加新的内容
参数:想向末尾增加哪些内容就传递谁,可以传递多个值,统一向末尾增加多项
返回:新增后数组的长度。原有的数组也会发生改变
扩展:向数组末尾增加内容也可用ary[ary.length]=10;
(2) pop:删除数组最后一项的内容
参数:没有
返回值:被删除的那一项的内容。原有的数组也会发生改变
扩展:ary.length--; -> 删除最后一项内容
(3) shift:删除数组中的第一项
参数:没有
返回值:被删除的那一项的内容。原有的数组也会发生改变
(4) unshift:向数组开头增加一项
参数:要添加的内容
返回值:新增后数组的长度。原有的数组也会发生改变
(5) splice: 即能实现删除,也能实现增加,还能实现修改
【删除】splice(n,m)
参数:从索引n开始,删除m个元素
返回值:把删除的内容以一个新数组的方式返回。原来的数组发生改变
扩展:ary.splice(n); -> 从索引n开始,删除到数组的末尾
ary.splice(0); -> 把原来数组中的每一项都删除(清空数组每一项),把之前的每一项的值以一个新的数组返回(克隆,但会修改原来的数组)
ary.splice(); -> 数组中一项都没有删除,返回的是一个空数组
ary.splice(ary.lenght-1); -> 删除最后一项
【修改】splice(n,m,x);
参数:从索引n开始,删除m个,用x替换删除的整个部分
返回值:把删除的内容以一个新的数组返回。原来的数组发生改变
扩展:ary[2]=300; -> 利用对象的操作方式也能修改某一项的值
【增加】splice(n,0,x);
参数:从索引n开始,一个都不删除,把x增加到索引n的前面
返回值:返回结果是一个空数组,原来的数组改变
扩展:ary.splice(ary.length,0,x); -> 把x增加在末尾
2.关于数组的截取和拼接
(1)slice:实现数组的截取,在原来的数组中截取某一部分
形式:slice(n,m)
参数:从索引n开始,找到索引m处(不包含m)
返回值:将找到的部分以一个新的数组返回,原来的数组不变
扩展:slice(n) -> 从索引n开始一直找到数组的末尾
slice(0)或者slice() -> 把原来的数组克隆一份一摸一样的新数组返回,原来数组不变
(2)concat:把两个数组拼接到一起
形式:ary1.concat(ary2) -> 把ary1和ary2拼接,ary2在后面
返回值:将两个数组拼接后返回拼接后的数组,原来的两个数组不变
扩展:ary1.concat() -> 把ary1克隆一份一摸一样的数组
3.把数组转换为字符串
(1)toString:把数组转换为字符串
形式:ary.toString()
返回值:字符串用逗号分隔,原来的数组不变
扩展:ary.toString() -> 对其转换没有影响
(2)join:按照每一个分隔符,把数组中的每一项拼接成一个字符串
返回值:把数组按照指定的分隔符进行拼接,原来的数组不变
扩展:ary.join("+") -> 加号也可换成其它符号
eval("1+2+3") -> 结果是6。js中把字符串变为js表达式是执行的一个方法
4.数组的排序和排列
(1)reverse:把数组进行倒序
形式:ary.reverse()
返回值:返回倒序后的数组,原来数组不变
(2)sort:给数组进行从小到大排序排序,
形式:ary.sort(function(a,b){
return a-b;
});
扩展:ary.sort() -> 这样只能处理十以内的数字进行排序,因为它是按照unicode编码的值进行排序
ary.sort(function(a,b){
return b-a
}); -> 给数组从大到小进行排序
5.只有在标准浏览器中兼容的方法,在IE6~8下不兼容的
(1)indexof/lastIndexOf:可验证当前的内容是否在数组中存在
含义:1)当前内容在数组中第一次/最后一次出现位置的索引,
如果数组中没有这一项,返回的结果还是-1,如果有这一项,索引是几返回的就是几,原数组不变
2)字符串中也有这两个方法,但是字符串的这两个方法兼容所有的浏览器,
而数组的这两个方法是不兼容的
(2)forEach/map:都是用来遍历数组中的每一项的
forEach:数组中有几项,函数就执行几次
形式:ary6.forEach(function(item,index){
console.log(item,index);
});
参数:item -> 当前遍历的数组中这一项的值。index -> 当前这一项值的索引。原数组不变
map:和forEach的语法一样,但是比forEach多加了一个把原来内容进行替换的功能
形式:ary6.map(function(item,index){
console.log(item,index);
});
返回值:原来数组不变,但可在原来数组基础上做更改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
var ary=[12,23,34,45];
//push:向数组的末尾增加新的内容
var res=ary.push(100,"小花");
console.log(res,ary);
//pop:删除数组最后一项的内容
var res=ary.pop();
console.log(res,ary);
//shift:删除数组中的第一项
var res=ary.shift();
console.log(res,ary);
// unshift:向数组开头增加一项
var res=ary.unshift(1000);
console.log(res,ary);
//splice:从索引n开始,删除m个元素
var res=ary.splice(1,2);
console.log(res,ary);
//splice:从索引n开始,删除m个,用x替换删除的整个部分
var res=ary.splice(1,2,999);
console.log(res,ary);
//concat:把两个数组拼接到一起,原来的数组不变
var ary1=[1,2,3,45];
var ary2=[90,99,78];
var newAry=ary1.concat(ary2);
console.log(newAry);
//toString:把数组转换为字符串
var res=ary.toString();
//把数组中的每一项进行相加求和
var ary3=[12,13,14];
console.log(eval(ary3.join("+")));//打印结果为39
//给数组内的数从小到大进行排序
var ary4=[1,4,2,4,6,8,10,7,99,77,40];
ary4.sort(function(a,b){
return a-b;
});
console.log(ary4);
//利用indexof判断某元素是否在数组中存在
var ary5=[1,2,3,4];
if(ary5.indexOf("7")>-1){
//说明7在数组中存在
}else{
//说明7在数组中不存在
}
//forEach/map:都是用来遍历数组中的每一项的
var ary6=[9,7,5,3];
ary6.forEach(function(item,index){
console.log(item,index);
});
//map还可以把每一项进行修改成Wie一个新数组返回,但原数组不变
var newAry6=ary6.map(function(item,index){
return item*10;
});
console.log(newAry6);
//查看更多的数组的方法
console.dir(Array.prototype);
</script>
</body>
</html>
3.3 数组去重的四种方法
1.利用对象的键值对去重(缺点:去重后的元素顺序会发生改变,建议用下面三种)
(1)把数组中的每一项的值当做一个对象的属性名和属性值存储起来
(2)在存储之前先判断当前项N是否存在,如果存在则是N,如果不存在则是undefined
(3)如果是N,就说明这一项已经出现过一次,就在数组中将这一项删除,如果是undefined就把当前项当做对象的属性名和属性值存储进去
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
var ary = [1, 1, 1, 23, 23, 1, 1, 4, 4, 5, 4, 5, 2, 1];
var obj = {};
for (var i = 0; i < ary.length; i++) {
//每次循环获取数组的当前项
var cur = ary[i];
if (obj[cur] == cur) {//说明对象中已经存在cur这一项了,也说明cur在数组中重复了,需要将这一项删除掉
/*
ary.splice(i,1);
当前删除,后面的每一项的索引都修改了,如果后面有很多项,非常的耗性能
*/
//用数组末尾那一项的值替换当前项
ary[i] = ary[ary.length - 1];
//再把数组末尾那一项的值删掉
ary.length--;
i--;
continue;
}
obj[cur] = cur;
}
console.log(obj);
console.log(ary);
</script>
</body>
</html>
2.for循环嵌套,利用splice去重
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
//此方法是比较常用的方法之一,也是es5中比较实用的方法之一
function newArr(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
// 如果第一个等于第二个,splice方法删除第二个
arr.splice(j, 1);
j--;
}
}
}
return arr;
}
var arr = [1, 1, 1, 23, 23, 1, 1, 4, 4, 5, 4, 5, 2, 1];
console.log(newArr(arr))
</script>
</body>
</html>
3.新建数组,利用indexOf去重
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
/*
此方法也是es5中比较简单的方法之一,
基本思路是新建一个数组,原数组遍历传入新数组,
判断值是否存在,值不存在就加入该新数组中;
值得一提的是,方法“indexOf”是es5的方法,IE8以下不支持。
*/
function newArr(array) {
//一个新的数组
var arrs = [];
//遍历当前数组
for (var i = 0; i < array.length; i++) {
//如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面
if (arrs.indexOf(array[i]) == -1) {
arrs.push(array[i])
};
}
return arrs;
}
var arr = [1, 1, 1, 23, 23, 1, 1, 4, 4, 5, 4, 5, 2, 1];
console.log(newArr(arr))
</script>
</body>
</html>
4.利用Set去重
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
//此方法是所有去重方法中代码最少的方法
function newArr(arr) {
return Array.from(new Set(arr))
}
var arr = [1, 1, 1, 23, 23, 1, 1, 4, 4, 5, 4, 5, 2, 1];
console.log(newArr(arr))
</script>
</body>
</html>
3.4 递归及定时器
实现1-100之间,把所有不能被3整除的数相加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
1.递归:当前函数自己调用自己执行
*/
//实现1-100之间,把所有不能被3整除的数相加
// 利用for循环实现
var total1 = null;
for (var i = 1; i <= 100; i++) {
if (i % 3 !== 0) {
total1 += i;
}
}
console.log(total1);
// 利用while循环实现
var total2 = null;
var j = 1;
while (j <= 100) {
j % 3 !== 0 ? total2 += j : null;
j++;
}
console.log(total2);
//利用递归实现
function sum(n) {
//如果n为0,说明已经相加完了
if (n === 0) {
return 0;
}
//如果n能够被3整除,就跳过这个数,判断下一个数
if (n % 3 === 0) {
return sum(n - 1);
}
//如果前面两个if都不满足,就让n相加
return n + sum(n - 1);
}
var total = sum(10);
console.log(total);
/*
-> sum(10) -> 10+sum(9) -> 10+sum(8) -> 10+8+sum(7)
-> 10+8+7+sum(6) -> 10+8+7+sum(5) -> 10+8+7+5+sum(4)
-> 10+8+7+5+4+sum(3) -> 10+8+7+5+4+sum(2) -> 10+8+7+5+4+2+sum(1)
-> 10+8+7+5+4+2+1+sum(0) -> 10+8+7+5+4+2+1+0
*/
//1-10之间所有能被2整除的数相乘
function cheng(n) {
if (n <= 1) {
return 1;
}
if (n % 2 === 0) {
return n * cheng(n - 1);
}
return cheng(n - 1);
}
var cheng1 = cheng(10);
console.log(cheng1);
</script>
</body>
</html>
定时器和递归
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
//利用setInterval实现定时器
var count1 = 0;
var timer1 = window.setInterval(function () {
count1++;
console.log(count1);
if (count1 === 10) {
window.clearInterval(timer1);
}
}, 1000);
/*
使用setTimeout实现一个和setInterval一样的功能:
使用递归的思想,每一次执行完成move方法后,
重新设置一个新的定时器,让定时器到一秒后重新执行move
*/
var count2 = 0;
var timer2 = null;
function move() {
/*
存在的问题:每一次执行move方法都会重新创建一个新的setTimeout定时器,
定时器执行一次就不再重新执行,但是并没有把它清除掉,
导致很多没用的定时器累积,占内存
解决方式:在每一次执行move,先把上一次没用的那个定时器先清除掉
*/
window.clearTimeout(timer2);
count2++;
console.log(count2);
if (count2 === 10) {
return;
}
timer2 = window.setTimeout(move, 1000);
/*
console.log(arguments.callee);
存储的是当前函数本身,等价于move
*/
}
move();
</script>
</body>
</html>
3.5 数组冒泡排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
冒泡排序的思想:让当前项和后一项进行比较,如果当前项大于后一项,两者交换位置
第一轮:
4>3 交换位置【3,4,5,2,1】
4<5 不交换位置【3,4,5,2,1】
5>2 交换位置【3,4,2,5,1】
5>1 交换位置【3,4,2,1,5】
已经把数组中当前最大的那个值放在数组的末尾位置
第一轮比较了四次,一共五个数,不用和自己比,最多比较四次
第二轮:
3<4 不交换位置【3,4,2,1,5】
4>2 交换位置【3,2,4,1,5】
4>1 交换位置【3,2,1,4,5】
把剩下项的最大项放在倒数第二位
第一轮已经把最大的数放在了末尾,所以第二轮不再和末尾比
第三轮:
3>2 交换位置【2,3,1,4,5】
3>1 交换位置【2,1,3,4,5】
第四轮:
2>1 交换位置【1,2,3,4,5】
每一轮当前项和后一项两两比较,把当前最大的那个纸放在后面
-》数组一共有五项只需要比较四轮(ary.length-1)
*/
/*
i轮数 i=0 i<ary.length-1
j每一轮比较的次数
i=0 第一轮 4 ary.length-1-0 ary.length-1 》不用和自己比
i=1 第一轮 3 ary.length-1-1
i=2 第一轮 2 ary.length-1-2
i=3 第一轮 1 ary.length-1-3
...
规律:每一轮比较的次数 ary.length-1-i
*/
/*
两者交换位置(不使用第三个变量)
var a=12;
var b=13;
a=a+b; -> a=25
b=a-b; -> b=25-13=13
a=a-b; -> a=25-12=13
使用第三个变量
var a=12;
var b=13;
var c=null;
c=a;
a=b;
b=c;
*/
function bubbleSort(ary) {
for (var i = 0; i < ary.length - 1; i++) { // i -> 轮数
for (var j = 0; j < ary.length - 1 - i; j++) { // j -> 每一轮比较的次数
if (ary[j] > ary[j + 1]) {
temp = ary[j];
ary[j] = ary[j + 1];
ary[j + 1] = temp;
}
}
}
return ary;
}
var ary = [5, 6, 3, 4, 2, 8, 1];
var res = bubbleSort(ary);
console.log(res);
</script>
</body>
</html>
3.6 数组快速排序
快速排序的思想:
(1)首先在数组中找一个“基准点”(一般把基准点选择为数组中间的这一项)
Math.floor(ary.length/2);
比如一共9项,获取的结果是4,正好是中间项。一共是10项,获取的结果是5,也接近中间项
(2)拿基准点和数组中的其他项进行比较,比基准点小的放左边,比基准点大的放右边
(3)以后的每一边都重复上述的两个操作,直到当前这一边只有一项的时候停止处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function quickSort(ary) {
//如果传递过来的数组只有一项了,就不需要再按照快排的思想拆了,直接把这个一项的数组返回即可
if (ary.length <= 1) {
return ary;
}
//找到基准点的索引
var pointIndex = Math.floor(ary.length / 2);
//通过基准点的索引在原来的数组中,删除这一项,并把基准点这一项的值获取到
var pointValue = ary.splice(pointIndex, 1)[0];
//拿基准点的值和原来的数组中每一项进行比较,把小于基准点的值放在左边,把大于基准点的放在右边
var left = [];
var right = [];
for (var i = 0; i < ary.length; i++) {
var cur = ary[i];
cur < pointValue ? left.push(cur) : right.push(cur);
}
//把左边排好序的数组,中间的基准点,以及右边排好序的数组拼接起来
return quickSort(left).concat([pointValue], quickSort(right));
}
var ary = [12, 13, 23, 14, 26, 34, 13, 16];
var res = quickSort(ary);
console.log(res);
</script>
</body>
</html>
3.7 数组插入排序
插入排序的思想(将其比喻成扑克牌):
(1)把第一张牌放在左手,以后拿到每一张牌的时候,和左手中的牌进行依次进行比较(一般来说我们的习惯是从后往前比较)
(2)如果当前的牌比倒数第一张小,再继续往左比,
(3)一直到遇到当前的牌已经比手里的某张牌大了,则把这张牌插入到某张牌的后面(某张牌下一张牌的前面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function insetSort(ary) {
//newAry存储的就是我左手中已经抓取的牌
var newAry = [];
//先抓第一张牌
newAry.push(ary[0]);
//一次把桌面上第二张及以后的牌抓到
for (var i = 1; i < ary.length; i++) {
var cur = ary[i];
//抓到当前牌之后,分别从后往前和左手中的牌进行比较(倒着循环进行比较)
for (var j = newAry.length - 1; j >= 0; ) {
if (cur < newAry[j]) {//当前新抓的牌比左手中的newAry[j]这张牌小
//继续和newAry[j]前面的牌比较
j--;
if(j===-1){//说明当前拿的这张牌比左手所有的牌都小,那么就把这张牌放在开头位置即可
newAry.unshift(cur);
}
} else {
//当前新抓的牌比左手中的newAry[j]这张牌大,放在newAry[j]这张牌的后面
//也相当于插入到newAry[j+1]这张牌的前面
newAry.splice(j+1, 0, cur);
j = -1;
}
}
}
return newAry;
}
var ary=[6,3,5,7,2,4];
var res=insetSort(ary);
console.log(res);
</script>
</body>
</html>
以下是借鉴其他博客的插入排序代码写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function insertionSort(array) {
var len = array.length;
//默认第一个已经排序,从第二个开始和前面的对比并插入
for (var i = 1; i < array.length; i++) {
//保存当前要拿来对比插入的数
var key = array[i];
//将key和前一个数相比
var j = i - 1;
//前一个数大于key时,将大的数放在后面
while (j >= 0 && array[j] > key) {
//将大的数后移一个位置(即j)
//此处不需要交换位置,因为还未找到key数的真正位置,
//还需要进行对比,直接覆盖就好,key已经保存了当前拿来插入的数
array[j + 1] = array[j];
//再和之前的一个数相比,直到比到第一个,即j < 0
//j < 0不符合while条件,跳出循环
j--;
}
//全部比完(跳出循环)后将key插入
array[j + 1] = key;
}
return array;
}
var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
console.log(insertionSort(arr));
//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
</script>
</body>
</html>
4. DOM
4.1 DOM获取元素的8种方法(根据其他博客的总结)
- 通过id获取(getElementById)
- 通过name属性获取(getElementByName)
- 通过标签名获取(getElementsByTagName)
- 通过类名(getElementsByClassName)
- 通过选择器获取一个元素(querySelector)
- 通过选择器获取一组元素(querySelectorAll)
- 获取html(document.documentElement)【document.documentElement是专门获取html这个标签的】
- 获取body的方法(document.body)【document.body是专门获取body整个标签的】
1.通过id获取(getElementById)
在整个文档中,通过元素的ID获取到这个元素对象(获取的是一个元素)
<div id="box"></div>
<script>
var box= document.getElementById("box");
</script>
- 上下文必须是document
- 必须传参数,参数是string类型,是获取元素的id
- 如果页面中id重复了,那么这个方法默认只获取第一个元素
- 返回值只获取到一个元素(返回一个DOM对象),没有找到则返回null
2.通过name属性(getElementsByName)
通过元素name属性的值来获取一组元素
<div id="box">
<input type="text" name="user" />
</div>
<script>
var userInput= document.getElementsByName("user");
</script>
- 上下文必须是document.内容
- 必须传参数,参数是获取元素的name属性(表单元素)
- 返回值是一个类数组,没有找到则返回空数组
3.通过标签名(getElementsByTagName)
在整个文档中,通过元素的标签名获取一组元素
<div id="box">
<p>段落1</p>
<p>段落2</p>
<p>段落3</p>
<p>段落4</p>
<p>段落5</p>
<p>段落6</p>
</div>
<script>
var oBox=document.getElementById("box");
var oPs=oBox.getElementsByTagName("p");
console.dir(oPs);
// oPs.length 代表获取元素的个数 --》oPs["length"]
//oPs[0]获取第一个p --》oPs.item(0)
</script>
- 上下文可以是document,也可以是一个元素,注意这个元素一定存在
- 参数是获取元素的标签名属性,不区分大小写
- 返回值是一个对象类型结果,并且是一个类数组,没有找到则返回空数组
4.通过类名(getElementsByClassName)
<div class="tab">
<ul>
<li>视频</li>
<li>新闻</li>
<li>综艺</li>
</ul>
</div>
<script type="text/javascript">
var oList=document.getElementsByClassName("tab");
console.dir(oList[0]);//获取tab中的第一个元素
</script>
- 上下文可以是document,也可以是一个元素
- 参数是元素的类名
- 返回值是一个类数组,没有找到则返回空数组
5.通过选择器获取一个元素(querySelector)
获取一个
<div id="box"></div>
<script>
var box= document.querySelector("#box");
</script>
- 上下文可以是document,也可以是一个元素
- querySelector()方法括号中的值是元素的选择器,所以前面加了”#”符号,使用的是id选择器
- 返回值只获取第一个元素
6.通过选择器获取一组元素(querySelectorAll)
获取多个,类数组集合
<div class="box">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
<div class="box">box4</div>
<div class="box">box5</div>
<script>
var box1= document.querySelector(".box");
var boxes= document.querySelectorAll(".box");
</script>
- 上下文可以是document,也可以是一个元素
- 参数是元素的选择器,querySelectorAll()获取到了所有class为box的元素集合
- 返回值是一个类数组
7.document.documentElement(获取HTML元素)
8.document.body(获取body元素)
var curWidth=document.documentElement.clientWidth||docuemnt.body.clientWidth;
//兼容所有浏览器的获取当前屏幕的宽度
小结:
1) 所有获取DOM对象的方法中,只有getElementById()和querySelector()这两个方法直接返回的DOM对象本身,可直接为其绑定事件。
2) getElementXXX类型的方法,除了通过Id获取元素,其他都返回一个集合,如果需要取到具体的DOM元素,需要加索引,如:document.getElementsByClassName(“box”)[0] =>获取class为box的所有元素中的第一个DOM元素。
3) querySelector()与querySelectorAll()两者的联系与区别:
联系: 两者括号中的取值都是选择器
区别: 当有多个class相同的元素时,使用querySelector()方法只能获取到第一个class为box的元素,而querySelectorAll()获取到了所有class为box的元素集合。
4.2 DOM中的节点和关系属性
1. 节点:Node 一个页面中的标签,文字,注释。。。都是节点
2. 获取关系的属性:
childNodes 获取所有的子节点
children 获取所有的元素子节点
parentNode 获取父亲节点
previousSibling 获取上一个哥哥节点
nextSibling 获取下一个弟弟节点
firstChild 获取所有子节点中的第一个
lastChild 获取所有子节点中的最后一个
3. 在js中需要掌握的节点类型:
nodeType nodeName nodeValue
元素节点(元素标签) 1 大写的标签名 null
文本节点(文字) 3 #text 文字内容
注释节点(注释) 8 #comment 注释内容
document 9 #document null
4. 在标准浏览器下,把space(空格)和enter(回车)都当做文本节点来处理
5. 举例: 模拟children方法,实现获取指定元素下的元素子节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div1">
<h1>课程体系</h1>
<ul>
<li>HTMl+css课程</li>
<li>JavaScript课程</li>
<li>Iava课程</li>
<li>HTML5课程</li>
<li>Node.js课程</li>
</ul>
</div>
<script type="text/javascript">
/*
getMyChildren:获取指定元素下的所有的元素节点
@parameter: --> 表示参数的意思
ele:要获取谁下面的,就把谁传进来
tagName:告诉别人获取的是哪种类型的元素,例如:“div”就是代表只获取div元素节点
@return:
最后获取的元素子节点
*/
function getMyChildren(ele,tagName) {
//1.弄一个空盒子放想要的元素,然后获取ele下的所有的子节点(包含文本,注释,元素)
var ary = [], nodes = ele.childNodes;
//var ary=[];
// var nodes=ele.childNodes;
//2.循环所有的子节点
for (var i = 0; i < nodes.length; i++) {
//3.把每一次循环得到的对应的节点复制给cur,而且可能是文本或者注释,元素等
var cur = nodes[i];
//4.只需要把元素的放入盒子,根据nodeType的值进行判断
if (cur.nodeType === 1) {//判断是否为元素节点
if (tagName) {
//5.如果传递了tagName,就进一步筛选
if (cur.nodeName.toLowerCase() === tagName.toLowerCase()) {//.toLowerCase()将大写转换成小写
ary.push(cur);
}
} else {
//6.如果没有传递,就默认把所有的元素都扔到盒子里
ary.push(cur);
}
}
}
return ary;
}
var oDiv = document.getElementById("div1");
console.log(getMyChildren(oDiv,"ul"));
</script>
</body>
</html>