一、绑定的click事件被触发多次
解决方法:在点击之后删除绑定的click事件
// 移除按钮的点击事件(要移除的事件名称,要移除的函数,指定移除事件句柄的阶段)
button.removeEventListener('click', onclick, false);
二、函数和js的特殊关系
1、函数
把需要的功能打包封装在一起组成函数。
函数一般包含函数声明和函数执行两部分。
函数大部分情况是指函数声明。
①要使用一个函数,必须将其定义在希望调用它的作用域内。
②传进来的参数不能加引号,不然就会变成字符串。
③传参:原始值(不会改变原值)、引用值(会影响实参的值)
function changeStuff(a, b, c){
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num); //10
console.log(obj1.item); // "changed"
console.log(obj2.item); // "unchanged"
④递归函数
使用repeat之后会将原来的字符串复制n次
在其他函数中调用的函数称为回调函数
2、问题:
- 只写 函数执行 行么?——不行,报错
- 只写 函数声明 是不是就可以了?——可以,不会报错,但页面不显示内容,没有用
- 函数声明必须要写在函数执行之前么?——可以,js会自己把代码过一遍(预编译)
- 函数声明可以写在if、for循环里么?——可以,满足条件的时候执行函数,不满足的时候会报错,但一般不会写在循环里面。
- 函数里面可以写函数么?——可以,但是使用不到函数里面的那个函数
3、求和函数
<body>
<script>
function mySum(num){
if(num>10000){
console.log("num太大了,不做");
return -1;
}
var sum = 0;
for(var i =1;i<=num;i++){
sum+=i;
}
return sum;
}
console.log(mySum(10)); //控制台显示55
</script>
</body>
4、先定义后执行
声明两次函数,用最后声明的,函数声明是可以被覆盖的。
预编译的时候会按代码顺序执行,先执行变量,碰到if的时候跳过,执行的时候会把函数提前。
函数里面包裹的函数:在函数里可以调用函数里面包裹的函数。
5、函数的返回值
1、返回:return。
函数运行完,需要有结果。
<body>
<script>
function 削水果(水果的名字="土豆",去皮的次数=10,大小块="小块"){
document.write("洗"+ 水果的名字 + "<br>");
for(var i=0;i<10;i++){
document.write("去皮"+(i+1)+"<br>");
}
document.write("切" + 大小块+ "<br>");
document.write("插上牙签"+"<br>");
return "cc吃掉了"; // 结果
}
var tt=0;
tt=削水果("苹果",2); // 将return的值赋给tt。
</script>
</body>
2、定义一个局部变量——写在function里面
var str = “” ;
str = 水果的名字 ;
等同于var str=水果的名字 ;
运行的结果为tt拿到了一碟小块的苹果
<body>
<script>
function 削水果(水果的名字="土豆",去皮的次数=10,大小块="小块"){
var str = "" ;
str = 水果的名字 ;
document.write("洗"+ 水果的名字 + "<br>");
for(var i=0;i<10;i++){
document.write("去皮"+(i+1)+"<br>");
}
document.write("切" + 大小块+ "<br>");
document.write("插上牙签"+"<br>");
str ="一碟"+ 大小块 + "的" + str; // 简单字符串的拼接
return str;
}
var tt=0;
tt=削水果("苹果",2);
document.write("<br>"+"tt拿到了:"+tt+"<br>");
</script>
</body>
3、return语句:
function 削水果(水果的名字){
return "准备好的水果";
}
cc在厨房里削水果——水果装在盘子里——tt在客厅看电视
厨房相当于函数——盘子相当于return——最后tt拿到了盘子里的水果
4、break和return
break是指跳出当前的循环,直接往下执行。
return是把结果返回给函数,代表函数运行结束。可与判断一同使用
6、函数的参数
1、函数名()——调用函数。
函数声明是不会被执行的。
参数——函数中可以改变的值。形参会接收实参的值。最好用英文。没有实参的时候,形参的值为undefined(未定义)。
2、函数的参数
①削水果
<body>
<script>
function 削水果(水果的名字){——水果的名字成为形参,形参会接收实参的值,等于在花括号里对应变量var 水果的名字;
document.write("洗"+ 水果的名字 + "<br>");
for(var i=0;i<10;i++){
document.write("去皮"+(i+1)+"<br>");
}
document.write("切小块"+"<br>");
document.write("插上牙签"+"<br>");
}
削水果("苹果");——苹果为函数的参数,实参,等同于在函数声明的花括号里写 水果的名字=“苹果”;
</script>
</body>
②如果没有实参——可设置一个默认值。默认值可以通过 实参||默认值 来设置。||表示或者的意思。
<body>
<script>
function 削水果(水果的名字){
if(水果的名字===undefined){
水果的名字="梨";——默认值
}
document.write("洗"+ 水果的名字 + "<br>");
for(var i=0;i<10;i++){
document.write("去皮"+(i+1)+"<br>");
}
document.write("切小块"+"<br>");
document.write("插上牙签"+"<br>");
}
削水果();
</script>
</body>
③可定义多个参数——多个参数之间用逗号隔开。
字符串需要加引号。
var x;
var y;
等同于 var x,y;
同理 function(水果的名字,去皮的次数,大小块)
3、形参——函数的变量声明;实参——函数的变量赋值。
可通过声明的时候设置默认值,即参数的初始化:
function(水果的名字=“苹果”,去皮的次数=10,大小块=“小块”)
# 三、JavaScript浏览器原理和js时间线
## 1、浏览器
多线程(可同时做多件事)——可做js引擎、UI渲染、事件、发起请求的线程、定时器的线程等
## 2、浏览器处理js事件是单线程的
编程方便,多线程容易出现问题
## 3、同步任务、异步任务(有先后)
## 4、js两大阶段
### 第一阶段——载入阶段(默认状态是同步的);
- ①浏览器获取页面内容,开始解析;
- ②生成DOM树
- ③同步现在外部引用文件,用js解析器对脚本进行解析,之后执行
- ④解析完成,浏览器渲染的同时有文件在下载,展示给用户
- ⑤载入阶段结束
### 第二阶段——事件阶段(默认是异步的)
## 5、js(编程语言,表现逻辑)的核心语法:逻辑
用途——实现业务的交互
## 6、web编程:与浏览器打交道,提供了好多方法
页面:加img、文字——DOM
底层(浏览器):BOM——存储、通信等
## 7、浏览器加载页面——简单的操作系统
- ①在输入网址之后,浏览器会把网址转换为IP地址(通过IP地址来定位),域名——为了让数字好记
- ②DNS服务器:浏览器拿到网址的时候,会将域名发送给DNS服务器,服务器会将域名转化为IP地址
- ③浏览器收到地址后会将地址*缓存在本地*
- ④浏览器向网址发送请求
- ⑤服务器收到请求网址,默认端口是80.(服务器可以当成是政府的办公大楼,办公大楼里有很多窗口,窗口就相当于是端口)
- ⑥服务器把请求的内容进行处理,返回给浏览器页面的内容
- ⑦浏览器收到文件内容,对内容进行解析
- ⑧人看到页面
# 四、 js控制标签切换显示
实现页面动态效果:实现小米闪购的菜单切换——背景颜色移动,同时下部的商品列表更新
1、需要将js引入到文件中,先引入到HTML最后(引入如下,因为js文件在js文件夹下,js文件夹与index.html同级)
```<script src="js/index.js"></script>```
2、在HTML文件中设置id,使得js可获取到元素
①HTML中:
```bash
<ul id="tabs">
<li class="active"><em>10:00</em><span><em>抢购中<br>距结束 02:07:29</em></span></li>
<li><em>14:00</em><span>即将开始</span></li>
<li><em>20:00</em><span> 即将开始</span></li>
<li><em>22:00</em><span> 即将开始</span></li>
<li><em>00:00</em><span> 明日开始</span></li>
</ul>
②在js中通过id获取元素
var tabs=document.getElementById("tabs")
③给ul中的li绑定事件,需要先获取到li,如下:
var tabs=document.getElementById("tabs").getElementsByTagName("li")
获取到的是完整的li数组列表——可通过浏览器的控制台查看:
console.log(tabs);
3、通过for循环来遍历li来绑定事件,可实现通过点击使背景移动
for(var i=0;i<tabs.length;i++){
tabs[i].onclick= showlist;
}
function showlist(){
for(var i=0;i<tabs.length;i++){
if(tabs[i]===this){
tabs[i].className="active";
}
else{
tabs[i].className="";
}
}
}
五、js控制商品切换显示
1、有5个商品标签,所以需要在HTML中复制5份ul出来:
<ul class="clearfix">
<li>
<div class="bg"><img src="img/1.jpg" alt=""></div>
<div class="info">
<a href="" class="name">小米小爱蓝牙音箱随身版 白色</a>
<p class="tips">小巧便携,一键唤醒小爱</p>
<p class="price">45.00元 <del>49元</del></p>
<a href="" class="btn">登录后抢购</a>
</div>
</li>
</ul>
2、修改对应的图片——用F12拷贝scr,存放入对应的文件夹中
3、调整HTML结构,找到CSS,通过ul来显示或者隐藏不需要的内容,是seckill-goods底下的 ul
修改的CSS代码如下:
.seckill-goods .active{
display: block;——活跃状态显示
}
.seckill-goods ul{
display: none;——使不显示
margin-right: -13px;
/* border: 1px solid black; */
}
在对应的HTML文件中的class中添加active,即可显示,如下:
<ul class="clearfix active">
4、可通过ID来获取元素,首先在div中添加id,如下:
<div id="lists" class="seckill-goods">
在js文件中通过id来获取对应的元素——div对象
var lists=document.getElementById("lists");
获取到div里的ul:
var lists=document.getElementById("lists").getElementsByTagName("ul");
通过console.log来调试代码,查看代码的执行程度:
console.log(lists);
5、使得商品随标签显示到不同界面
function showlist(){
for(var i=0;i<tabs.length;i++){
if(tabs[i]===this){
tabs[i].className="active";
lists[i].className="clearfix active";——清除浮动之后active
}
else{
tabs[i].className="";
lists[i].className="clearfix";
}
}
}
六、js控制菜单固定
1、实现菜单栏一直固定在页面(不管滚轮怎么滚动)——固定对应的div即可。
该标签栏div对应的class是seckill-nav,找到对应的CSS中写相应属性的地方,添加如下代码:
.seckill-navfixed{
position: fixed;——使标签栏固定在了页面
}
2、使标签栏固定在顶上(CSS中)
.seckill-navfixed{
position: fixed;
top:60px;
}
3、使滚轮滚动的时候才固定在顶上,需要获取滚轮滚动了多少,在js中写代码
var scrollTop=document.documentElement.scrollTop;
console.log(scrollTop);——获取滚轮滚动了多少
4、需要监听事件:监听浏览器本身页面滚动的事件(window.onscroll),在js中写:
window.onscroll=function(){
var scrollTop=document.documentElement.scrollTop;
if(scrollTop>=260){
///seckill-nav seckill-navfixed
}else{
seckill-nav
}
}
执行该操作之前,需要先获取到对应的div,首先要给div赋予id,在HTML中写如下代码:
<div id="seckillNav" class="seckill-nav">
5、在js中实现标签栏随鼠标滚动
var seckillNav=document.getElementById("seckillNav")
window.onscroll=function(){
var scrollTop=document.documentElement.scrollTop;
if(scrollTop>=260){
///seckill-nav seckill-navfixed
seckillNav.className="seckill-nav seckill-navfixed"
}else{
seckillNav.className="seckill-nav";
}
}
6、兼容性问题:火狐,谷歌可用上述方法获取
var scrollTop=document.documentElement.scrollTop;
IE、苹果自带的浏览器需要用其他方法来获取:
//ie——document.body.scrollTop;
//苹果自带的浏览器——window.pagrYOffset;
7、使得浏览器可兼容,通过或(||)运算符实现:
var scrollTop=document.documentElement.scrollTop||window.pagrYOffset||document.body.scrollTop;
七、JS练习
1、定义函数的方式
function a() { alert(1); }
var a = function() { alert(1); }
var a = new Function('alert(1);');
var a = (function() { return function() { alert(1); }})();
var a = function() { return function() { alert(1); }}();
2、Object对象具有如下方法
hasOwnProperty、isPrototypeOf
3、数组实例方法
sort、join、concat
4、RegExp对象上的方法
test、exec、compile
5、类型检测方法
typeof、instanceof、Object.prototype.toString、constructor方法
6、知识点
1、AJAX流行的原因是让页面可以局部加载和重绘。
2、JSON跟JS普通对象的区别:属性名必须加引号、不能使用单引号做字符串边界、属性值不能是函数或者表达式。
3、const body = document.getElementsByTagName(“body”)[0];const body = document.querySelector(“body”);是获得body元素的正确方法。
4、DOM的操作方法有appendChild、getAttribute、replaceChild。
5、XMLHttpRequest对象上的方法有send、open。
6、responseText、responseXML可以用来获取服务器响应内容的XMLHttpRequest属性。
7、onclick、onselect事件属性可以置于HTML标签内部并且有效。
8、preventDefault、stopPropagation是event对象上的方法。
9、注册事件的方法正确的是document.getElementById(“test”)[“onmousemove”] = function(e){}、document.getElementById(“test”).onclick = function(e){};、document.getElementById(“test”).addEventListener(“click”, function(e){});
10、原生具备Iterator接口的数据结构有:Array、String、Map、arguments。
7、node.js
1、对外提供Node模块:module.exports
2、导入Node模块:require()
3、httpServerResponse上的方法有write、end、writeHead
4、Writable、Duplex、Transform的stream类型是可写的。
5、.clear、.exit、.load是REPL的内置命令。
6、on、once、emit是EventEmitter对象上的方法。
7、w+、r、wx模式可以用于fs模块打开文件。
8、exit、beforeExit、uncaughtException事件可以用于全局process对象。
9、exec、spawn、fork方法在child_process模块上。
八、JS交互
1、交互——人与浏览器、页面之间的互动。
①先找到需要交互的元素→元素=document.getElementById("myID");
②监听事件→页面是需要交互的。
元素.onclick=函数的名字;——点击
元素.onmouseover=函数的名字;——移入
元素.onmouseout=函数的名字;——移出
③修改元素的内容→元素.innerHTML=字符串;
2、①首先通过ID获取元素
<body>
<button id="btn">点击</button>
<script>
var btnDom =document.getElementById("btn");
</script>
</body>
②绑定点击事件
<body>
<button id="btn">点击</button>
<script>
var btnDom =document.getElementById("btn");
btnDom.onclick = btnOnclick; // 绑定事件
function btnOnclick(){
console.log("点击了");
} // 定义函数
</script>
</body>
③可将匿名函数直接赋值给事件——与②效果一样
btnDom.onclick =function (){
console.log("点击了");
}
④修改元素内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>交互</title>
<style>
div{
width: 300px;
height: 500px;
background-color: greenyellow;
}
</style>
</head>
<body>
<p>想出门么?</p>
<div id="myDiv"></div>
<button id="btn">点击</button>
<script>
var btnDom =document.getElementById("btn");
btnDom.onclick = btnOnclick;
function btnOnclick(){
var myDivDom=document.getElementById("myDiv");
myDivDom.innerHTML+="点了";——修改div元素里面的内容
console.log("点击了");
}
</script>
</body>
</html>
3、匿名函数——没有名字的函数。
function (){
console.log("点击了");
}
4、鼠标移入、移出:
<script>
var btnDom =document.getElementById("btn");
btnDom.onclick = btnOnclick;
function btnOnclick(){
var myDivDom=document.getElementById("myDiv");
myDivDom.innerHTML+="点了";
console.log("点击了");
}
btnDom.onmouseover=function(){
var myDivDom=document.getElementById("myDiv");
myDivDom.innerHTML+="鼠标移入";
}
btnDom.onmouseout=function(){
var myDivDom=document.getElementById("myDiv");
myDivDom.innerHTML+="鼠标移出";
}
</script>
九、运算符
一元运算符
1、+(正号)、-(负号)、++(自增)、–(自减)
a++类似于a=a+1
2、字符串前加+,结果会变为数字
<body>
<script>
var a="11";
var b=+a;
var c=-a;
var d=a;
</script>
</body>
结果为a=“11”,b=11,c=-11,d=“11”
3、自增++(与自减语法相同):
<body>
<script>
var a=1;
a++;
var b=1;
b=b+1;
</script>
</body>
结果为a=2,b=2
4、++a;——a先加1后赋值
a++;——先赋值后加1
<body>
<script>
var a1=1;
var b1=a1++;——类似于b1=a1,a1=a1+1
var a2=1;
var b2=++a2;——类似于a2=a2+1,b2=a2
</script>
</body>
结果为a1=2,a2=2,b1=1,b2=2
5、运算结果为CC=104;TT=4100
<body>
<script>
var cc=1;
cctest=cc++ + ++c + + "100";——先是cc++,cc的值变为2,++cc,cc的值变为3,将字符串转化为数字
var tt=1;
tttest=+(tt++ + ++tt + "100") ;——先运算小括号里的表达式,先是tt++,先赋值后tt的值变为2,++tt,,1+3,之后将值转化为字符串,变为两个字符串相加,变为“4100”,将字符串转化为数字4100
</script>
</body>
注释:(cctest=1 + ++c + + “100”;)(cctest=1 + 3 + + “100”;)(cctest=1 + 3 + 100;)**
(tttest=+(1 + ++tt +“100”);)(tttest=+(1 + 3 + “100”);)(tttest=+(4 + “100”);)(tttest=+(“4” + “100”);)(tttest=+“4100”;)(tttest=4100;)
6、运算顺序:一元运算符>二元运算符 >三元运算符
十、元素.innerHTML
1、变量和值:变量即容器。
2、运算符:把多个值或变量进行组合计算。%——取余。(数字或者字符串等)
3、操作手段:
if条件判断
for循环;while循环
switch选择
4、①var x;——变量的定义;
②1;“cc”;——值
③x=1;——通过=把右边的值赋给变量
④x+=1;——x=x+1;为了简洁好看
x*=1;
<body>
<script>
var x;//变量的定义
1;
"cc";
x=1;
x+=1;
x*=1;
</script>
</body>
5、if条件判断
①if()——括号里面跟的是条件
②if(){
执行的内容;
}
③if(){
满足条件执行的内容;
}else{
不满足条件执行的内容;
}
④if(){
满足条件执行的内容;
}else if(){
不满足条件执行的内容;
}
6、for循环——里面也有break、continue;break是指跳出for循环;continue是指当前循环结束,重新执行for循环。
①for(初始化;条件;修改值){
条件过后执行;执行完之后执行修改值
}
②continue经常配合if使用:
for(初始化;条件;修改值){
if(判断条件){
continue;——满足判断条件,不做后续的执行步骤,从for循环开始
}
条件过后执行;执行完之后执行修改值
}
7、switch选择
switch(x){
case 1:执行内容;
break;——跳出循环外,不写break会继续往下执行case 2.
case 2:执行内容;
break;
}
8、表现如下效果:
*
**
***
****
①先设置一行
<body>
<script>
var len=4;
var oneline="";
for(var i=0;i<len;i++){
oneline +="*";
}
document.write(oneline);
</script>
</body>
②设置多行
<body>
<script>
var floor=5;——行数
for(var j=0;j<floor;j++){
var len=j+1;
var oneline="";
for(var i=0;i<len;i++){
oneline +="*";
}
document.write(oneline+"<br>");
}
</script>
</body>
③加div的话,div是在上面,*在div下方
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
height: 200px;
background: greenyellow;
}——设置div的样式
</style>
</head>
<body>
<div>
这是一个div。
</div>
<script>
var floor=5;——行数
for(var j=0;j<floor;j++){
var len=j+1;
var oneline="";
for(var i=0;i<len;i++){
oneline +="*";
}
document.write(oneline+"<br>");
}
</script>
</body>
④ document.write无法修改标签里面的内容。
通过 元素=document.getElementByld(“myID”); 的方法来找到对应的内容;——通过Id来获取
通过 元素.innerHTML 方法来修改标签里的内容。
使得*放入div标签里:先找到div标签;修改div里面的内容
<body>
<div id="myDiv">
这是一个div。
</div>
<div>
这是第二个div。
</div>
<script>
var my=document.getElementById("myDiv");——先获取到div标签
my.innerHTML= "***";——将div里的内容该为***
var allLine="";——定义一个allLine为空的字符串,后续可将所有行的内容放入
var floor=5;——行数
for(var j=0;j<floor;j++){
var len=j+1;
var oneline="";
for(var i=0;i<len;i++){
oneline +="*";
}
oneline+="<br>"——给每一行内容换行
allLine+=oneline;——每执行一次加一次前一行的内容
//document.write(oneline+"<br>");
}
my.innerHTML= allLine;——将allLine的值赋值给my,my为元素div里的内容,即修改div里的内容
</script>
</body>
十一、关于数字导出表格后显示为科学计数法
方法原则就是转换成字符,而且拼接上别的字符使其不会被当成数字处理。
1、在数字前加‘\t’
(e[v] = "\t" + e[v].toString())
2、添加 style样式,转化为文本格式
<td style="mso-number-format:'\@';">2105300716356709e1</td>