Day01
一、JavaScript的介绍
js:是一个运行在浏览器端的 解释型 弱类型 面向对象 脚本语言
三部分组成:
ECMAScript(核心语法) + DOM(和网页挂钩) + BOM(和浏览器挂钩)
1、环境-类型
浏览器:
自带了JavaScript解释器,打开浏览器就可以自动运行
学习node.js时,会安装一个独立的js解释器
编译型:
在程序正式执行之前,需要检查语法是否正确,如果不正确,直接不运行 比如:JavaScript/c
解释型:
在程序执行之前,不需要检查语法是否正确,直接运行,直到碰到错误就停止 比如:JavaScript/php
强类型:
变量保存的数据,是由数据的类型来决定的 比如:java
弱类型:
变量保存的数据是可以随意的,数据类型由数据来决定 比如:JavaScript
1
“1”
2、面向对象(抽象)
对象名.属性名;
对项目.方法名();
3、特点
1.可以使用一切的编辑工具写js代码
2.解释型
3.弱类型
4.面向对象
5.可以完成一切css完成不了的效果(轮播图、选项卡、购物车...)
二、如何使用
1、使用方式:2种
1.在HTML页面中写上script便签,再在里面写js代码
ex:
<script>
js代码
</script>
2.创建一个xx.js的文件,通过HTML外部引入
ex:
<script src:“js路径”></script>
2、输出方式/打桩输出(帮助我们以后检查错误)
1.在控制台输出日志:
console.log(先要输出的东西)
2.在页面输出日志:
document.write(想要输出的东西)
3.在弹出框输出日志:
alter(想要输出的东西)
3、变量
ps:创建后,可以再次更改
何时使用:
以后反复使用到的数据,都要提前把它保存在一个变量之中,以后使用变量名相当于就是在使用变量的值
语法:
var 变量名 = 值;
特殊:
1.变量名不是随意的
1.不能以数字开头
2.建议驼峰命名法或下划线命名法
3.命名要尽量的见名知意
另外:
2.如果变量是name,不管保存的数据类型是什么,都会悄悄的转化为一个字符串
3.变量名不能是关键字
4.变量可以只创建不赋值,默认值为undefined,但是要牢记undefined是一个垃圾,拿来做什么都要不得
5.如果多个变量连续创建---简写:
var 变量名 = 值,变量名= 值,...,变量值 = 值;
4、常量
ps:创建后,不允许修改!
语法:
const 常量名 = 值;
其他特殊点和 变量 一模一样
5.数组的基础
1.定义:
1.数组都是线性排列的,除了第一个元素,每个元素都有唯一的前驱元素,除了最后一个元素,每个元素都有唯一的后继元素
2.每个元素都有一个自己的位置,称之为:下标,下标都是从0开始到最大长度-1结束
2.数据类型有哪些?(两大类)
原始/基本/值类型
1.number - 数字:取值有无数个,直接写,不用加任何东西(颜色为蓝色)
2.string - 字符串:取值有无数个,但是必须加上“”或者''(颜色为黑色)
3.boolean - 布尔:取值只有2个分别是:true 和 false,一般用于判断(颜色是蓝色)
4.null - 空:取值只有一个,就是null,唯一的作用就是用于释放内存,节约内存空间,提升网页的性能(颜色是灰色)
5.undefined - 取值只有一个,就是undefined,牢记undefined就是一个 垃圾 ,拿来做什么都要不得
ps:
查看数据类型:typeof(变量);
引用/对象类型(11个)
*Sring Number Boolean -> 包装型
*Array *Fuction Date(日期) Math(数学) *RegExp(正则:验证码)
Error(错误)
*Object(面向对象开发方式)
Globa(全局对象) - 只有在浏览器中被Window对象代替了,自然会保存着全局变量好局部变量,只不过window可以省略不写,在node.js中全局对象叫global
包装类型:专门用于将原始类型的值封装为一个引用类型的对象
原因:原始类型的值原本就是没有任何属性和方法,意味着原始类型本身是不支持 . 做任何操作得,为了方便操作,给“Sring Number Boolean”提供了包装类型(提供了属性和方法)
何时使用:只要使用原始类型的变量调用属性或方法的时候,自动包装
何时释放:方法调用完毕后,自动释放包装类型,又变成了原始类型
ps:null和undefined不能使用,这俩没有提供包装类型
2.创建数组:2种
1.直接量方式:var arr=[]; - 空数组
var arr=[数据1,...];
2.构造函数方式:var arr=new Array(); - 空数组
var arr=new Array(数据1,...)
ps:这种方法有坑! - new Array(num);
3.获取数组之中的元素:
数组名[i]
4.后续添加/替换元素;
数组名[i]=新数据;
如果下标处没数据,则为添加,如果下标处有数据,则为替换
5.数组具有三大不限制
1.不限制元素的类型
2.不限制元素的长度
3.不限制下标越界 --- 不是一个好东西
如果获取元素是,下标越界,返回的是一个undefined
如果添加元素时,下标越界,会得到一个稀疏数组,如果搭配上循环去遍历获取每个元素,会得到很多的undefined
问题:数下标可能会输错,导致下标越界
解决:数组中有一个唯一的属性:length
语法:数组名.length
作用:获取到数组的长度,长度是从1开始的
三个固定套路:
1.向末尾添加元素:arr[arr.length]=新数据;
2.获取数组的倒数第n个元素:arr[arr.length-n]
3.缩容:删除倒数n个元素:arr.length -= n;
6.遍历数组:很多情况不会拿出某个元素来使用,而是拿出每个元素来进行形同或者相似的操作
搭配上循环:
固定公式:
for(var i+0;i<arr.length;i++){
arr[i];
}
补充点1:
1.面试题:
按值传递:var a=x;var b=a;修改a、b变不变或者修改b、a变不变
传递的值如果是原始类型:
其实是复制了一个副本给对方,两者互不影响
传递的值如果是引用类型:(js中不是原始类型就是引用类型(函数、数组、都是引用类型))
因为引用类型很大,比原始类型大很多,不可能存在变量本地,只是保存了一个地址,其实是赋值了自己的地址给对方,两者用的是同一个地址值,一个修改另一个也会变化
2.如何释放掉一个引用类型:
一定要看清楚有几个变量引用者这个引用类型,每个变量都要释放后才能释放干净
在js底层有一个垃圾回收器,只有垃圾回收器的计数器(记录着这个数据有几个引用着)为0的时候才会删除不要的数据
建议:代码都要封装为一个函数,函数整的一切变量都会自动释放掉
hash数组(关联数组):下标是可以自定义的
索引数组的下标无具体的意义,不便于查找
如何使用:
1.创建:2步
1.创建空数组:var arr=[]
2.为空数组添加自定义下标并且赋值:arr["自定义下标"]=新值;
2.访问元素:arr["自定义下标"];
3.强调:hash数组的length会失效,永远为0!
遍历hash数组:不能再使用for循环,必须使用for in循环
ps:不需要设置从哪里开始到哪里结束,纯自动化的,专门为了遍历hash数组的存在
for(var i in 数组名){
i;
数组名[i];//当前此元素
}
不止能遍历hash数组,也能遍历索引数组
建议:索引数组使用for,hash数组使用for in
4.hash数组的原理:
hash算法:将字符串计算出一个尽量不重复的数字(地址值),字符串内容相同,则计算出来的数字也是一定相同的
添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将要保存的数据放到地址保存起来
获取元素:将指定的自定义下标交给hash算法,得到一个和当初保存时一样的数字(地址值),通过此地址找到你当初保存的数据,取出来使用
5.js里面一切的东西都是对象,万物皆是对象,除了undefined和null,一切对象的底层都是hash数组
3.数组的API
1.arr 转 str:
var str=arr.join("自定义连接符");
固定套路:2个
1.笔试题:将数组里面的内容拼接为一句话/单词 - 无缝拼接,其实就拼接了一个空字符串
var arr=["h","e","l","l","o"," ","w","o","r","l","d"]
var str=arr.join("")
console.log(str)
2.将数组拼接为DOM页面元素
//拿数据
var arr=["-请选择-","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆"]
//将数组拼接为页面标签字符串
var str="<开始标签>"+arr.join("</结束标签><开始标签>")+"</结束标签>";
//innerHTML 支持识别标签
sel.innerHTML=str
2.数组拼接:添加元素的新方式
将传入的实参全部拼接到arr的末尾
var newArr=arr.concat(新值1,arr1,...)
特殊:
1.不修改原数组,只返回一个新数组
2.concat支持传入数组参数,会将传入的数组打散为单个元素再拼接
3.截取子数组:
根据传入的开始下标截取到结束下标
var subArr=arr.slice(starti,endi+1)
特殊:
1.不修改原数组,只会返回一个新数组
2.含头不含尾
3.endi可以省略不写,如果省略,会从starti位置一直截取到末尾
4.starti也可以省略,如果两个实参都省略,那么会从头到尾完全的复制一份,此操作也叫做深拷贝 - 复制了一个副本给对方
5.支持负数参数,-1代表倒数第1个
------------------------------以上三个API都是不修改原数组的--------------------------
------------------------------以下几个API都会修改原数组------------------------------
4.删、插、替:
删除:var dels=arr.splice(starti,n)//n代表删除的个数
特殊:
虽然直接修改原数组,但是也有返回值,返回的是被删除的数据组成的一个新数据,及时没有删除也会返回一个空数组
插入:arr.splice(starti,新值,...);
特殊:
1.原starti位置的元素以及后续元素都会向后移动
2.尽量不要插入一个数组,会导致数组一些是一维,一些是二维,不方便遍历
替换:var dels=arr.splice(starti,n,新值,...)
特殊:
删除的个数和插入的个数不必相同(可同可不同)
5.翻转数组:arr.reverse()
6.数组排序
1.笔试题:冒泡排序:前一个元素和后一个元素进行对比,如果前一个>后一个,两者交换位置,但是循环一次后只有最大的一个数字到了最后,所以再开循环反复使用
固定公式:
var arr=[31,21,54,4376,69,8,8,65,643,52,3,321,5,47,69,87,643,524]
for(var j=1
for(var i=0
if(arr[i]>arr[i+1]){
var m=arr[i]
arr[i]=arr[i+1]
arr[i+1]=m
}
}
}
console.log(arr)
2.正式开发时:
默认:将数组中的元素转为字符串后,再按位PK每个字符的Unicode号(ASCII码)
问题1:希望按照数字的升序排列:
arr.sort(function(a,b)){
//此函数叫匿名回调函数,回调函数不需要程序员自己调用
//console.log(a)
//console.log(b)
return a-b
//如果返回的是一个正数:说明后一个>前一个
//如果返回的是一个负数:说明后一个<前一个
//如果返回的是一个0:说明后一个=前一个
//sort方法会根据你返回的正数、负数、0,来自动考虑要不要换位置
}
问题2:希望按照数字的降序排列:
arr.sort(fuction(a,b){
b-a
})
强调:
1.只要网页上有功能带有排序,底层一定一定是一个数组,因为js中只有数组可以排序
2.只要网页上有随机功能,底层一定是用到了随机数公式
7.栈和队列:添加元素和删除元素的新方式:
栈:其实就是数组,只不过一端封闭,只能从另一端进出
如何使用:
开头进:arr.unshift(新值,...)
//添加元素的新方式,向前添加,缺点:导致其余元素的下标都发生变化
开头出:var.first=arr.shift()
////,一次只能删除一个,缺点:导致其余元素的下标都发生变化
结尾进:arr.push(新值,...)//添加元素的新方式,向后添加
结尾出:var last=arr.pop**()
队列:其实就是数组,只不过一端进,从一端出:
开头进:arr.unshift(新值,...)
结尾出:var last=arr.pop()
结尾进:arr.push(新值,...)
开头出:var first=arr.shift()
ps:ES3数组的API已学完,ES5还提供了3组6个API...
8.二维数组:数组的元素,又引用这另一个数组
创建:
var arr=[
["张三",18,900],
["李四",19,1000],
["王麻子",20,700]
]
访问:arr[行下标][列下标];
特殊:
列下标越界,返回undefined
行下标越界,会报错,因为行下标越界已经得到一个undefined,undefined不能加[]做操作
遍历二维数组:必然两层循环,外层循环控制行,内层循环控制列
for(var r<0
for(var c=0
console,log(arr[r][c])
}
}
9.ES3还提供了3组6个API
1.判断:2个
every:每一个,要求所有元素都满足条件才会为true,只要一个不满足则为false,非常类似于&&
var bool=arr.every(function(val,i,arr){
//val - 当前值
//i - 当前值的下标
//arr - 判断条件
return 判断条件
})
2.遍历:拿到数组中的每个元素做相同 或 相似的操作
forEach - 直接修改原数组
arr.forEach(function(val,i,arr){
操作;
})
map - 不修改原数组返回一个新数组
var newArr=arr.map(function(val,i,arr){
return 操作
})
3.过滤和汇总:
过滤:筛选出需要的部分,原数组不会发生变化
var subArr=arr.filter(function(val,i,arr){
return 判断条件;
})
汇总:
var result=arr.reduce(fuction(val,i,arr){
return prev+val
},基础值)
以上6个API都是在简化for循环
补充:
ES6箭头函数:用于简化一切匿名回调函数:
固定公式:
fuction去掉,()和{}之间添加=>,如果形参只有一个,呢么()可以省略,如果函数体只有一句话,那么{}也可以省略,如果函数体只有一句话并且是return,那么return和{}都可以省略
字符串(String)
1.概念:多个字符组成的只读字符数组(只读:所有的字符串的API都不会修改原字符串,都会返回一个新的字符串)
2.字符串和数组的与不同点相同点
相同点:
1.字符串中的个数:str.length
2.获取字符串中的某个字符:str[i]
3.遍历字符串
4.所有数组不修改原数组的API,字符也可以使用(concat,slice)
不同点:
1.所有数组能直接修改原数组的API字符串都不能用,比如排序只有数组才能使用
3.StringAPI:就是一些只有字符串可以使用的函数,不需要我们创建,直接使用
1.转义字符:\
作用:
1.将字符串中和程序冲突的字符转为原文
"\"" '\''
2.包含特殊功能的符号
换行:\n
制表符:\t 大空格,和敲tab键效果一样
3.输出 unicode 编码的字符:
\u4e00 --- 19968
\u9af5 --- 40869
2.大小写切换:将字符串中的每个字符统一的转为大写或者小写
何时使用:只要程序不区分大小写,就要先统一的转为大写或小写,再比较(验证码)
如何使用:
大写:var upper=str.toUpperCase()
小写:var upper=str.toLowerCase()
3.获取字符串中指定位置的字符:str.charAt(i) === str[i]
4.获取字符串中指定位置的字符的ASCII码:
var 原文=String.fromCharCode(ascii)
5.检索字符串:检查索引,检查下标:获取关键字下标
var i=str/arr.indexOf("关键字",starti)
从starti位置开始,查找右侧第一个关键字的第一个字符的位置,starti可以省略,默认从0位置开始查找
返回值:
找到了,返回第一个关键字的第一个字符的下标位置
没找到,返回-1,不关心下标为多少,只关心下标是不是-1
作用:判断有没有!
强调:数组也能使用此方法,数组这个方法是后期才添加上的,原本此方法只有字符串才能使用,比如老IE就没有此方法
笔试题:默认只能获取到第一个关键字的下标,如何才能获 取到所有的关键字的下标?
var str="no zuo no die no can no bibi"
var index=-1
while((index=str.indexOf("no",index+1))!=-1){
console.log("找到了,下标为:"+index)
}
6.截取字符串:3个
var substr=str/arr.slice(starti,endi+1)
//用法和数组的用法完全一致
var substr=str.substring(starti,endi+1)
//用法几乎和slice一致,但是不支持负数参数
var substr=str.substr(starti,n)
//n代表的事截取的个数,不必考虑含头不含尾
7.拼接字符串:var newstr=str.concat("新字符串",...) 还不如+运算
8.替换字符串:
var newstr=str.replace("固定关键字"/正则表达式."新内容");
9.切割/分割/分割字符串:
作用:将字符串转为数组
var arr=str.split("自定义切割符")
注意:
1.切割后,切割符就不在了
2.如果写的是"",切散每一个字符
10.去掉空白字符:str.trim/trimStrat/trimEnd()
扩展:js如果创建元素:3步
1.创建空标签:var elem=document.creatElement("标签名")
2.为其设置必要的属性和事件:
elem.属性名="属性值";
elem.on事件名=function(){操作}
3.挂载上树/渲染页面:父元素.appendChild(elem)
Math对象
1.作用:专门提供了数字计算的API,不需要创建,直接使用。
2.API
1.取整:3种
1.上取整:超过一点,就取下一个整数
var num=Math.ceil(num)
//小数位数不能超过15位,否则此方法只能取整,不能上取整
2.下取整:无论超过多少,都会省略小数部分
var num=Math.floor(num)
3.四舍五入取整:
var num=Math.round(num)
//只看小数位数第一位
//取整的方式:以上三个+parseInt(str 去掉单位)+num.toFixed
4.num.toFixed(d)
优点:
1.可以四舍五入,并且保留指定小数位数,d其实就是保留的小数位数.
2.解决浏览器带来的舍入误差,2-1.6=0.39999999,就能用num.toFixed(d)
缺点:
1.结果是一个字符串,建议搭配上parseFloat()使用
笔试题:
不允许使用toFixed的情况,自己封装一个函数,由用户传入数字和保留位数,实现四舍五入操作:
funct toFixed(num,d){
num*=(10**d)
num=Math.round(num)
num/=(10**d)
return num
}
var result=toFixed(Math.PI,2)
console.log(result)
6、运算符
1.算术运算符:+ - * / %
特殊:
%:取余/模,两个数相除,取余
作用:
1.任意数 %2 -判断奇偶
2.取出某个数字的后n位
1234%10 - 4
1234%100 - 34
带有隐式转换:悄悄的会将数据类型转换,默认:都是左右两边转为数字再运算
true -> 1 false -> 0 undefined -> NaN null -> 0 "1000" -> 1000 "1000px" -> NaN
NaN:Not A Number:不是一个数字。但是它确实是数字类型,但是不是一个有效数字,没有优点,但是有两个缺点
1.参与任何的算术运算符结果仍为 NaN
2.参与任何的比较运算结果都是false
+ 运算的特殊:
如果碰上一个字符串,左右两边都是悄悄的转为字符串,+运算不再是 +运算,而是拼接操作
2.比较运算符:>,<,>=,<=,==,!=,===,!==
结果:一定是一个布尔值
带有隐式转换:默认左右两边都会悄悄转为数字再比较大小
特殊:
1.如果参与比较的左右两边都是一个字符串,则会安位PK每个字符的十六进制Unicode号(十进制的ASCII码)
数字0-9<大写A-Z<小写a-z<汉字
常识:
汉字的第一个字是 一 Unicode号是 4e00 ASCII码值是 19968
汉字的最后一个字是 龥 Unicode号是 9fa5 ASCII码值是 40869
2.NaN参与任何的比较运算结果都是false
判断 x 是否是NaN:
!isNaN(X);
结果是一个布尔值:
true - 数字
false - NaN
3.undefined == null - true
解决:
全等:不带隐式转换的等值比较(===),要求值相同并且数据类型也要相同
ps:
!==;
3.赋值运算符:=,+=,*=,/=,%=
1.=:赋值
将 = 右边的东西保存到 = 左边的变量名之中
2. +=,*=,/=,%= 可以理解为一种升级写法,运算后再保存会变量本身
ex:
i = i + 1 ----- i += 1;
4.逻辑运算符:综合比较-用于写
&&:与(并且)
全部条件都满足,结果才为 true,只要有一个条件不满足就为 false
||:或者
全部条件都不满足,结果才为 false,只要有一个条件满足就为 true
ps:
! - 颠倒布尔值
5.自增自减运算符:++ , --
i++ -> i+=1 -> i=i+1
自增:固定的每次只能+1
累加:+= 每次加几由程序员自己决定
笔试题:
前++ 和 后++的区别?
1.如果单独使用,前++和后++没有任何区别
2.如果参与了塔其他表达式,变量始终都会+1,但是前++和后++的返回值不同
前++:返回的是加过后的新值
后++:返回的是加之前的旧值
6.位运算
左移:m<<n 读作m左移了n位 -> m*2的n次方
右移:m>>n 读作m右移了n位 -> m/2的n次方
极不推荐使用原因:底数只能为2
扩展:
用户输入框:
var 变量 = prompt(“提示文字”)
Day02
一、分支结构
1.控制语句共有三个结构
顺序结构:默认从上往下一次执行每一行代码
分支结构:通过条件判断,选择部分代码执行
循环结构:通过条件判断,选择要不要重复执行某块代码
2.分支结构的几种方式
1.if...else...(3种)
一个条件,一件事,满足就做,不满足就不做
if(条件){
操作1;
}
一个条件,两件事,满足就做第一件,不满足就做第二件
if(条件){
操作1;
}else{
默认操作;
}
多个条件,多件事,满足谁就做谁
if(条件){
操作1;
}else if{
操作2;
}else if{
操作3;
}else{
操作4;
}
注意:
1.else..if...想写多少写多少,由程序员自己决定
2.else 可以省略,但不推荐,如果不写,条件都不满足的情况,则什么都不会发生
3.分支走了一条路,就不会走别的路
2.switch...case... 分支
语法:
switch(变量/表达式){
case 值1;
操作1;
breake;
case 值2;
操作2;
breake;
default:
默认操作;
}
特殊:
1.问题:
默认只要一个case满足后,会将后续所有的操作都全部做完
解决:
break;
建议:
每一个case的操作后面都跟上一个break
有的地方也可以不加break:
1.最后一个操作default可以省略break
2.如果中间多个条件,做的操作是一样的,可以省略掉中间部分
2.case在做比较的时候是不带隐式转换的
3.default可以省略不写的,不推荐,如果不写,条件都不满足的情况,则什么都不会发生
面试题:
if 和 Switch 的区别?
1.Switch...case...:
优点:执行效率高,速度快,比较时,case做的不是范围查找,而是等值比较
缺点:必须要知道最后的结果是什么才可以使用
2.if...else...:
优点:可以做范围判断
缺点:执行效率慢,速度慢,做的是范围查找
3.三目运算:简化分支
语法:
条件?操作1:默认操作; --- if...else...
条件1?操作1:条件2?操作2:条件3?操作3:默认操作; ---if...else...if...else...
注意:
1.默认操作不能省略,省略了会报错
2.如果操作复杂,不能使用三目运算,操作只能有一句话,如果操作有多句话推荐使用Switch或if
!页面上一切数据js获取到的都是字符串类型!
二、强制(显示)数据类型转换
1.转字符串(2种)
1.var Str = x.toString();
x不能为undefined和null,会报错,undefined和null不能使用 . 做任何操作,因为不是对象
2.var str=String(x);
*万能*所有类型都能转字符串,极不推荐使用,完全等效于隐式转换,不如 +""
综上不重要:页面上一切数据js获取到的都是字符串类型
2.转数字
1.parseint(str/num); parse-解析 专门用于将字符串转为整数
执行原理:从左往右依次读取转换每个字符,碰到非数字字符就停止转换,如果一来就不认识则为NaN,!不认识小数点!
ex:
console.log(parseInt(35.5));
console.log(parseInt("35.5"));
console.log(parseInt("3hello5"));
console.log(parseInt("hello35"));
console.log(parseInt("35px"));
console.log(parseInt(".35px"));
console.log(parseInt(true));
console.log(parseInt(false));
console.log(parseInt(undefined));
console.log(parseInt(null));
2.parseFloat(str); - parse解析 Float浮点型 - 专门用于将字符串转为小数
执行原理:几乎和parseint一致,认识第一个小数点
console.log(parseFloat(35.5));
console.log(parseFloat("35.5"));
console.log(parseFloat("3hello5"));
console.log(parseFloat("hello35"));
console.log(parseFloat("35.5px"));
console.log(parseFloat(".35px"));
console.log(parseFloat("35.5.5"));
3.number(x); *万能* 任何类型都能转为数字,完全等效于隐式转换,不如:-0,*1,/1
3.转布尔
boolean(x);*万能的* 任何类型都能转为布尔,完全等效于隐式转换,不如:!!x
只有6个位false:0,“”,undefined,NaN,null,false 其余全部都是true
day03
1.循环结构
循环结构:反复执行相同或者类似的操作
循环三要素:
1.循环条件:开始-结束,循环次数
2.循环体:做的操作是什么
3.循环变量:记录着当前在哪一次,会不断地变化
2.3种循环
1.while循环
语法:
var 循环变量 = 几;
while(循环条件){
循环体;
循环变量变化;
}
执行原理:首先创建出循环变量,判断循环条件,如果条件满足,则做一次循环体操作,并不会退出循环体,会回过头来再做一次循环体操作,直到条件不满足,才会退出循环
特殊:
1.有时候需要使用死循环:默认永远不会停下来的循环
何时使用:
不确定循环次数的时候
while(true){死循环}
2.死循环也会停?
break;退出整个循环,大多数搭配死循环来使用
continue;退出本次循环,下一次依然会执行
2.for循环:和while循环的原理一样,但比while看上去更加的简洁,更加的舒服
语法:
for(var 循环变量=几;循环条件;循环变量变化;){
循环体;
}
特殊:
死循环:for(;;){}
面试题:
while 和 for 的区别?
while和for在原理上几乎没有区别
一般的说,在不确定循环次数的时候,会使用while循环 -- 死循环
一般的说,在能确定循环次数的时候,会使用for循环
3.do...while...循环:废物
语法:
var 循环变量 = 几
do{
循环体;
循环变量的变化;
}while(循环条件)
面试题:
while 和 do...while的区别
区别只看第一次,如果第一次条件满足,没有什么区别,
但如果第一次条件都不满足,那么while一次都不执行,但do...while会执行一次
3、function的基础
1.概念:function叫函数也叫方法,先预定义好,以后可以反复使用的代码段
2.如何使用:2步
1.定义/创建/声明:
function 函数名(){
函数体/代码段;
}
注意:
函数创建后,不会立刻执行,需要调用函数才会执行
2.调用函数:2种
1.在js内部写:函数名();程序员写几次就调用几次
2.在HTML页面绑定事件
<elem onclick="函数名()"></elem> -- 所有元素都能绑定事件
3.何时使用函数:
1.不希望打开页面就立刻执行
2.希望用户来触发,提升用户的体验感
3.以后每一个独立的功能都要封装为一个函数,函数在js里面的地位极高,函数是js的第一等公民
4.一阶段已见过函数:
rotate(30deg);
url(xx.jpg);
这种叫带参函数:2步
1.创建出带有形参的函数
function 函数名(形参,...){
函数体/代码段;
}
2.使用带有形参的函数时,必须传入实参
函数名(实参,...)
注意:
传参的时候顺序是不能乱得,必须和形参的顺序一一对应,数量不多不少
总结:
1.不带参数的函数:用于执行一些固定操作
2.带参数的函数:可以根据我们传入的实参的不同,做的略微不同
循环和函数都能反复执行,有何区别?
1.循环:几乎是一瞬间就执行完了
2.函数:需要调用后才会执行
day04
1.自定义函数
1.定义:需要先预定义好,以后可以反复使用的一个代码段
2.何时使用:不希望打开页面立刻执行,以后可以反复使用,希望用户触发
3.如何使用:
1.创建:2种
1.声明方式 创建函数
function 函数名(形参函数){
操作;
return 返回值/结果;
}
2.直接量方式 创建函数 -- 不推荐
var 函数名=function (形参列表){
操作;
return 返回值/结果;
}
函数的变量名其实就是一个变量名
2.调用
var 接住返回的结果=函数名(实参列表);
其实return的本意就是退出函数,但是如果return后面跟着一个数据,顺便将数据返回到函数作用域的外部,但是return值负责返回,不负责保存,所以调用函数时要自己拿个变量来接住,就算省略return,默认也有,会return一个undefined
3.作用域:2种
1.全局作用域:全局变量 和 全局函数,在页面的任何一个位置都可以使用
2.局部作用域:局部变量 和 局部函数,在当前函数调用时,内部可用
变量 的使用规则:优先使用局部的,局部没有找到全局要,全局也没有那就会报错.
特殊点:
缺点:
1.千万不要在函数中对着未声明的变量直接赋值,会造成全局污染
全局污染:全局本来没有这个东西,但是被函数作用域给添加上了
2.局部可以使用全局的,但是全局不能使用局部的
解决: return
4.声明提前:只会出现在笔试题中
规则:
在程序正式执行之前,将var声明的变量(轻)和function声明的函数(重),都会悄悄的集中定义在当前作用域的顶部,但是赋值留在原地
强调:
声明方式创建的函数会完整的提前(第一种)
直接量方式创建的函数不会完整提前,只有变量名部分会提前(第二种)
何时使用:永远不会自己使用,只会在笔试题中干扰
只要遵守以下规则:
1.变量名和函数尽量不要重复
2.先创建后使用
5.重载:相同的函数名,根据传入的实参不同,自动选择对应的函数去执行,但是js不支持,函数名如果重复了,后面的会覆盖掉前面的
目的:减轻程序员的压力
解决:在函数颞部自带一个arguments的对象(类数组对象),不需要自己去创建,哪怕没有形参也能接受住所有实参,默认的长度(length)为0
固定套路:
1.通过下标去获取传入的某一个实参:arguments[i] - i从0开始
2.通过length去获取到底传入了几个实参:arguments.length,通过判断传入的实参的不同,在内部去写判断,从而变相的实现重载
day05
1、DOM
1.DOM:Document Object Model
文档对象模型专门用于操作HTML文档的,提供了一些方法
2.DOM树得到概念:DOM将HTML看作是一个倒挂的树状结构,但是树根不是HTML的标签,而是document的对象
document的对象:不需要自己创建,由浏览器的js解释器自动创建,一个页面只有一个document树根
作用:可以通过树根找到自己想要的任何一个DOM元素/节点/对象(属性和方法)
DOM会将页面上的每一个元素、属性、文本、注释等等都会被视为一个DOM元素/节点/对象
3.查找元素:两大方面
1.直接通过HTML的特点去查找元素
1.通过ID查找
var elem=document.getElementById(“id值”);
特殊:
1.返回值:找到了返回当前找到的DOM元素,没找到返回一个null
2.如果出现多个相同的id,只会找到第一个
3.忘记此方法,不推荐使用,id不好用,一次只能找一个元素,id留给后端使用
2.通过标签名查找元素
var elems=document/已找到的父元素.getElementsByTagName(“标签名”);
特殊:
1.返回值:找到了返回一个类数组DOM集合,没找到得到一个空集合
2.js只能操作DOM元素,不能直接操作DOM集合
解决:要么通过下标拿到某一个元素,要么通过遍历拿到每一个元素
不一定非要从document开始查找,如果从document去找,会找到所有的元素,可以换成已经找到的某个父元素
3.通过class查找元素
var elems=document.getElementByClassName(“class名”);
特殊:
1.返回值:找到了返回一个类数组DOM集合,没找到得到一个空集合
2.js只能操作DOM元素,不能直接操作DOM集合
解决:要么通过下标拿到某一个元素,要么通过遍历拿到每一个元素
不一定非要从document开始查找,如果从document去找,会找到所有的元素,可以换成已经找到的某个父元素
2.通过关系去获取元素:前提条件:必须先找到一个元素才可以使用关系
父元素:elem.parentNode; - 单个元素
子元素:elem.children; - 集合
第一个子元素:elem.firstElementChild; - 单个元素
最后一个子元素:elem.lastElementChild; - 单个元素
前一个兄弟:elem.previousElementSibling; - 单个元素
后一个兄弟:elem.nextElementSibling; - 单个元素
不希望影响到其他元素,只希望影响到自己就使用关系去查找
3.操作元素:前提:先找到元素,才能操作元素,3方面
1.内容:
1.elem.innerHTML - 获取和设置开始标签到结束标签之间的内容,支持识别标签的
获取:elem.innerHTML;
设置:elem.innerHTML=“新内容”;
2.elem.innerText - 获取和设置开始标签到结束标签之间的纯文本,不识别标签
获取:elem.innerText;
设置:elem.innerText=“新内容”;
3.input.value - 专门获取/设置input里面的内容
获取:input.value;
设置:input.value=“新内容”;
2.属性:
获取属性值:elem.getAttribute(“属性名”);
设置属性值:elem.getAttribute(“属性名”,“属性值”);
简化版:
获取属性值:elem.属性名;
设置属性值:elem.属性名=“属性值”;
简化版的缺点:
1.class必须写为className
2.不能操作自定义属性
3.样式
使用样式的方式:3种
1.内联样式
2.内部样式表
3.外部样式表 - 一阶段做开发应用都是用外部样式表
获取样式:elem.style.css属性名;
设置样式:elem.style.css属性名=“css属性值”;
特殊点:
1.css属性名,有横线的地方。去掉横线,变为小驼峰命名法
border-radius -> borderRidius
2.小缺陷:获取时,只能获取到内联样式,不能获取到外部样式
一切的获取往往都是为了判断
一切的设置往往都是添加或者修改