JavaScript:简称JS,是一个运行在客户端/浏览器的【解释性】【弱类型】【面向对象】脚本语言。
想要运行js需要运行环境:
- 浏览器自带js解释器
- node.js需要安装环境
编译型:在程序正式运行之前,会检查有没有报错,如果有报错直接不运行,比如Java、c++、c#...(严格的)
解释型:在程序正式运行之前,不会检查有没有报错,直接运行,碰到错误后就会停止,比如:javascript、node.js、php(自由的)
弱类型:在创建一个变量时,想放什么数据类型的数据就放什么(非常自由)
强类型:在创建变量之前,必须先规定,此变量可以保存什么数据类型,才能往里面放入对应的数据类型的数据(严格)
面向对象(万物皆对象):一切对象都有两个对象(属性和方法)
对象名.属性名
对象名.方法名()
一切一阶段做不到的事,都靠二阶段 原生js(轮播图,购买商品数量的加减....)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新的一天:加油哦!</title>
<script type="text/javascript" src="../js/one.js"></script>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>
目录- JavaScript:简称JS,是一个运行在客户端/浏览器的【解释性】【弱类型】【面向对象】脚本语言。
- 引入方式
- 打桩输出
- 注释
- 变量和常量
- 数据类型
- 数据类型转换
- 运算符
- ascii码
- 符号的优先级
- 分支语句
- 函数function
- 声明提前
- 按值传递
- 预定义全局函数:
- 循环
- 数组
- String
- DOM:Document Object Model:文档对象模型,专门用于操作html文档的,提供了一些方法
引入方式
- 直接在html上写一个script的双标签,里面书写js代码 - 临时测试玩法
- 在外部创建有个js文件,在其中写入js代码,html进行引入 - 正式开发玩法
<script src="路径">//此处不可以在写代码</script>
打桩输出
作用:检测代码是否有问题,找错,找bug
- 在控制台输出:console.log(想要输出的对象) //console控制台 log日志
- 在页面上输出:document.write(想要输出的东西) //document文档 write写入 能够识别标签;但是是个垃圾,如果搭配上点击事件,会替换原页面的内容。
- 弹出一个小框:alert(想要输出的内容) //垃圾:卡住html页面,用户不关掉,就只能看白板
- 在页面上弹出提示和用户输入框:prompt(提示文字) 卡住html页面,用户不关掉,就只能看白板
注释
作用:方便后期维护
- 单行注释 //
- 多行注释
/*内容*/
变量和常量
硬盘:外部存储器:外存,保存文件/数据
CPU:中央处理器,计算速度
内存:内部存储器,保存的是应用在执行过程中,所需要的一些数据(变量就是一个内存),我们取的变量名就是一个内存地址
变量var
可以保存数据,如果数据繁琐,以后可以使用变量名,相当于就是在使用变量的值;变量顾名思义,值以后可以改变。
-
语法:var 变量名=变量值;
-
特殊:
- 变量名不是随意的
- 不能数字开头,可以数字结尾
- 见名知意,驼峰命名
- name是一个关键字,不管你保存的数据类型是什么,最后都会悄悄地变成一个字符串
- 千万不要拿着关键字当变量名
- 可以不保存数据,会有一个默认值undefined,undefined是个垃圾,拿来干什么都要不得 - 非常不推荐大家创建变量不赋值
- 创建多个变量时可以简写,var只写一次,每个变量之间使用,进行分割
- 变量名不是随意的
常量const
一旦创建,值不允许修改
-
语法:const 常量名=值;
-
现实生活中哪些是常量?但是常量其实很少,代码中也会很少使用
1、一周7天
2、pi - 3.1415926....
3、一年12个月
4、地球的公转速度/自转速度
5、一年365/366天
数据类型
-
原始/基础/值类型:5个
-
number 数字类型,取值有无数个
-
string 字符串类型,取值有无数个,但是需要加上""或''括起来
-
boolean 布尔类型,取值只有两个:true(真/对) 或 false(假/错),一般用于做比较判断是才会出现
-
null 空,释放你不再需要的内存/变量,节约内存空间
-
undifined 拿来干什么都要不得,这是我们祖师爷犯下的一个错误
-
-
***引用/对象类型:11个
*String Number Boolean -> 为什么这三个人即使原始类型又是引用类型?原因是他们三个具有包装类型?
*Array *Function Date(日期) Math(数学) *RegExp(正则->表单的验证)
Error(错误)
*Object(面向对象开发方式)
Global(全局对象:保存着全局变量和全局函数) -> 特殊:浏览器中没有global,global被window给代替了,只不过window可以省略不写
只有JavaScript中global才被代替为了window,而且node.js后端语言中!全局对象就叫global。- ***面试题:什么是包装类型? 包装类型:专门将原始类型的值封装为一个引用类型的对象 为什么:原始类型的值原本是没有任何属性和方法的,意味着原始类型本身就是不支持.做操作的 但是前辈们发现字符串经常会被我们程序员所使用/操作 为了方便我们程序员为这三个人提供了包装类型,从值->对象(提供了很多属性和方法) 何时使用:只要你试图用原始类型的变量去调用属性或方法时,自动包装 何时释放:方法调用完毕后,包装类型就会自动释放,又变回了一个原始类型的值 为什么undefined和null不能使用. - 没有包装类型
数据类型转换
js获取到的页面上的一切东西,一定都是字符串
如果你想要查看数据类型:typeof(查看的东西);
隐式转换
-
算数运算符的隐式转换(默认:悄悄的将左右两边的东西,转为一个数字,再运算)
-
+运算,碰上一个字符串,两边都会悄悄的变成一个字符串,+运算,不再是+运算,而是一个拼接操作
-
别的数据类型也可以转为数字
true->1
false->0
null->0
undefined->NaN //只要是转为数字,但是不知道该转为什么数字,结果一定为NaN -
其实- * / %字符串也可以转为数字,前提要是一个纯数字组成的字符才可以,但凡包含了一个非数字字符则为NaN
"100"->100
"100px"->NaN -
、NaN:Not A Number,不是一个数字,但是确实是数字类型,不是一个有效数字
没得优点,但是有2个缺点:
1、NaN参与任何算术运算,结果仍为NaN
2、NaN参与任何比较运算,结果永远为false,带来了一个问题:我们没有办法使用普通的比较运算来判断该数据是不是NaN,NaN连自己都不认识自己
解决:!isNaN(x);
true->是一个有效数字
false->是一个NaN -
学完隐式转换,依然没解决一个事(给有单位的变量进行算数运算)
"100px"*2=NaN
"100px"+100="100px100" 所以接下来学习强制转换 ↓
-
显示/强制转换
隐式转换出来的结果不是我们想要的,我们就可以手动调用一些方法,强制转为我们需要的数据
- 转字符串:页面上一切的数据默认都是字符串
- var str=x.toString();//x不能是undefined和null。undefined和null不能使用.去访问任何东西
2. String(其他元素类型)可以将任何元素类型转换为字符串。完全相当于隐式转换,还不如直接用+
-
转数字:3种
-
*parseInt(str/num); parse->解析 Int->整型
原理:专门为字符串和小数转为整数数字准备的,从左向右依次读取每个字符,碰到非数字字符就停止转换,
如果一来就碰到了不认识的字符,则为NaN。 !!!不认识小数点!!!
console.log(parseInt(100.5));//100 console.log(parseInt("100.5"));//100 console.log(parseInt("100px"));//100 console.log(parseInt("px100"));//NaN console.log(parseInt("1px00"));//1 console.log(parseInt(true));//NaN console.log(parseInt(false));//NaN console.log(parseInt(undefined));//NaN console.log(parseInt(null));//NaN
-
、*parseFloat(str); parse->解析 Float->浮点型,小数
原理:几乎和parseInt一致,但是认识第一个小数点
console.log(parseFloat(100.5))//100.5 console.log(parseFloat("100.5"))//100.5 console.log(parseFloat("100.5px"))//100.5 console.log(parseFloat("px100.5"))//NaN console.log(parseFloat("10px0.5"))//10 console.log(parseFloat("10.5.5.5"))//10.5 console.log(parseFloat(".555"))//0.555
- Number(any);//此方法事万能的,任何人都可以转为数字
//垃圾:完全等效于隐式转换,还不如x-0 *1 /1 %1
-
-
转布尔:
- Boolean(x);任何数据都可以转为布尔
- 返回值大部分都为true,只有6个(0,空字符串,null,undefined,NaN,false)为false。
- 在分支,循环条件中,判断其会不会执行
- 用逻辑运算符非进行隐式转换
- !!null ---->false
- Boolean(x);任何数据都可以转为布尔
运算符
赋值运算符:
- = -= += /= %=
- i++和++i的区别:
- 单独使用没有区别
- 参与表达式使用,变量中的值都会+1
- 前置++ 返回的是加了后的新值
- ++后置 返回的是加之前的旧值
算数运算符: +-*/%
- 特殊:1、%:取余,俗称模,两个数相除,不去商,而且除不尽的余数
5%2 -> 1
3%5 -> 3
作用:
1、最大的作用就是判断奇偶性,num%2,如果等于0说明是偶数,如果等于1说明是奇数
2、获取某个数字的后几位
console.log(1234%10);//4
console.log(1234%100);//34
console.log(1234%1000);//234
3、控制一个数字永远不超过某个数字
num%3 -> 结果永远不会超过3 (1%3=1 2%3=2 3%3=0)
2、*算数运算都具有隐式转换:悄悄地都会转为数字,再运算
特殊:+运算,只要碰上一个字符串,则悄悄的两边都会转为字符串,+运算不再是+运算,变成了一个拼接操作 - 计算机很笨,虽然记忆能力很强(机械硬盘(永久保存)/固态硬盘(有效期10年)):计算机带有摄入误差,解决:num.toFixed(d);//d代表保留的小数位数,会四舍五入的功能
缺陷:搭配上一个parseFloat()使用最好,返回的结果是一个字符串
比较运算符:> < >= <= == === != !==
-
结果为布尔值
-
隐式转换:默认,转换为数字,再比较大小(出口全等和非全等)
-
如果参与比较的左右两边都是字符串,则按位PK每个字符的十六进制unicode号(十进制ascii码)
0-9<A-Z<a-z<汉字 48<=数字<=57 65<=大写字母<=90 97<=小写字母<=122 19968<=汉字<=40869
-
undefinednull;//true;
区分:undefined=null;//false === !== 不带隐式转换的等值比较和不等比较,要求数值相同,并且数据类型也要相同
function String(x){ if(x===null){ return "null"; }else if(x===undefined){ return "undefined"; }else{ return x.toString(); } // }
逻辑运算符:
-
&&:与,并且。要求全部条件都满足,结果为true,只要一个条件不满足就会false。
全部为true,才为true
一个false,则为false -
||:或者,要求全部条件都满足,结果为false,只要一个条件满足就true
全部为false,才为false
一个true,则为true -
! :颠倒布尔值
-
短路逻辑:如果前一个条件,已经能够得出最终结论了,则不看后续
-
&&短路:如果前一个条件满足,则后一个操作执行,如果前一个条件不满足,则后一个操作不执行
目的:简化【简单的】if分支:1、一个条件一件事,满足就做不满足就不做 2、操作只能有一句话
简化:条件&&(操作);
对比:(大于500,打八折)
以前:if(total>=500){total=0.8}
现在:total>=500&&(total=0.8) 因为&&的优先级比=的优先级高,因此加个小括号- ||短路:如果前一个为true,后一个不看 - 实现浏览器的兼容性,二选一操作
e=e||window.event;
-
三目运算
目的:简化分支
- if(){}else{}------> 简化为:条件?执行代码1:执行代码2;
- if(){}else if()else{}...------> 简化为:条件?执行代码1:条件?执行代码2:执行代码3;
位运算
左移:m<<n 表示m左移了n位,翻译:m*2的n次方
- 3的4次方----》3<<2------->`(3*2)*2`
右移:m>>n 表示m右移了n位,翻译:m/2的n次方
底数只能为2
ascii码
- 获取字符串中第一个字符的ascii码:str.charCodeAt(0);
数字:48-57
大写字母:65-90
小写字母:97-122
汉字:19968(4e00)-40869(9fa5)
符号的优先级
由高往低排序:
- ()
- ipt.value
- ++ --
- 逻辑非
分支语句
if()else{}分支
1、只有条件满足是才会执行操作,一个条件一件事,满足就做不满足就不做
if(条件){
操作
}
2、条件满足是才会执行操作,条件不满足则执行默认操作,一个条件两件事,满足就做第一件,不满足就做第二件
if(条件){
操作
}else{
默认操作
}
3、多个条件多件事,满足谁就做谁
if(条件1){
操作1
}else if(条件2){
操作2
}else{
默认操作
}
注意:1、第三种写法:else if可以有多个
2、分支只要走了一条路,就不会再看其他路了
3、else其实可以省略不写,但是不推荐,如果条件都不满足,则什么都不会执行
switch...case分支
- 语法:
switch(变量/表达式){
case 值1:
操作1;
case 值2:
操作2;
default:
默认操作
} - 特殊:
- case 的比较不带隐式转换
- 问题:默认只要一个case满足后,会将后面所有的操作全部做完
解决:break;
建议:每一个case的操作后都跟上一个break
有的地方也可以不加break:- 最后一个操作default可以省略break
- 如果中间多个操作做的事儿是一样,可以省略中间部分
- default可以省略不写,但如果条件都不满足,则什么都不会执行
- 面试题:if VS switch ?
- switch...case...,缺点:必须要知道最后的结果是什么才可以使用,在case中不能做范围判断,只能做等值判断
优点:执行效率相对较高 - if:缺点:执行效率相对较低
优点:可以随意的做范围判断 - 建议:代码优化时,要尽量的将所有的 if...else... 换成 switch...case...
- switch...case...,缺点:必须要知道最后的结果是什么才可以使用,在case中不能做范围判断,只能做等值判断
函数function
函数,也称之为方法,需要【预定义】好的,以后就可以【反复使用】的【代码段】
创建与使用函数
-
创建/定义/封装函数
-
声明方式:function 函数名(){
若干代码
return 返回值;
};
-
直接量方式:var 函数名=function(形参列表){//通过此处看出函数名其实也是一个变量名,衍生出,elem.on事件名这一坨其实就是函数名,无非涨得长了点
函数体;
return 返回值;
} -
return的本意,退出函数的意思
只不过如果return后面跟着一个数据,会顺便将其返回到全局作用域之中,但是只负责返回不负责保存!
所以再调用函数时,如果有return,记得拿一个变量接住他
调用函数:var result=函数名(实参列表)
-
-
使用/调用函数
函数名()
注意: 1、调用几次,就会执行几次
2、交给用户来触发,只需要在某个元素上绑定点击事件:
<div onclick="函数名()">内容</div>
- 何时使用:
1、不希望打开页面立刻执行,而在需要时调用,或者由用户来触发
2、希望能够反复执行,不需要刷新页面
3、以后任何一个独立的功能体,都要单独封装在一个函数之中(你做的每一个作业)
4、函数在js中的地位最高:第一等公民地位,以后要有封装的思想,!!!函数里面的变量会自动释放
带参数的函数:
何时使用:如果我的函数体,希望根据传入的实参的不同,做的略微不同
-
创建:形参:形式参数,其实就是一个变量名,但是不需要写var,而且默认保存的也是undefined
function 函数名(形参,形参,...){
若干操作/代码段;
} -
调用:实参:实际参数,真正的值,需要在你调用函数时从外部传入进去
函数名(实参,实参,...) -
特殊:1、传参的顺序一定要一一对应上,并且数量也要对应
2、不是一定要带参数的函数,才是好函数,具体要不要带参数,要看我们的需求
如果你的函数体事固定的 - 则普通函数就够了
如果你的函数体是根据参数的不同,做的略微不同 - 则带参数的函数完成
作用域:2种
-
全局作用域:成员:全局变量和全局函数,在任何位置都可以访问|使用.
-
函数/局部作用域:成员:局部变量和局部函数,只能在【函数调用时内部可用】
带来了变量得使用规则:优先使用局部的,局部没有找全局,全局没有就报错
特殊:
1、千万不要对着未声明的变量直接赋值:a=1; - 会导致全局污染,全局本来没有,突然就被添加上了一坨内存,建议任何变量使用之前一定要先var
2、儿子不孝啊,局部的东西全局居然不能用,解决:return 返回值;
3、哪怕没有写return,其实也会悄悄给你return一个undefined,默认
4、return一般只会出现再函数的最后,而且只能出现一次
5、其实前辈们提供给我们的方法,大部分底层都有return操作,因为前辈们考虑到了,调用了他这个方法过后得到的结果可能对我们以后有用
声明提前
在程序正式执行之前
会将var声明的变量和function声明的函数
集中提前到当前作用域的顶部,但是赋值留在原地
变量比函数轻
我们写代码绝对不会碰到,只要遵守规则:1、先创建后使用 2、变量名和函数名尽量的不要重复
只会在鄙视中碰到:如果以后你碰到先使用后创建,多半都是在靠你声明提前
按值传递
-
如果传递的是【原始类型的值】
修改一个变量,另一个变量是不会受到影响的,其实是复制了一个【副本】给对方 -
如果传递的是【引用类型的对象】:Array、Function
修改一个变量,另一个变量是会受到影响的,因为两者使用的是【同一个地址值】 - 浅拷贝:好像是复制了,但是复制的不全
预定义全局函数:
前辈们提前创建好的,我们可以直接使用的,在哪里都可以使用
-
编码和解码:- 玩玩悄悄话
问题:url中不允许出现多字节字符,如果出现会乱码
utf-8编码格式下,一个汉字,占3字节
解决:发送前,前端将用户输入的多字节字符编码为单字节字符(符号、字母)
发送后,后端将单字节字符解码为多字节原文编码:var code=encodeURIComponent("原文"); 解码:var 原文=decodeURIComponent(code); 其实百度根本就没做这个操作,这个东西在某次浏览器更新后,就自带此功能了,当场就淘汰了
-
isFinite(num); 判断num是不是无穷大,true->有效数字 false->无穷大
哪些会为false:NaN,分母为0(java就会错),Infinity -
牛逼的:parseInt/Float/isNaN/eval()
- eval(str);解析字符串(去掉字符串的引号)
- console.log(eval(‘1+2+3’))会直接得到结果 6
- eval(str);解析字符串(去掉字符串的引号)
循环
while循环
- 语法:
var 循环变量=几;
while(循环条件){
循环体;
循环变量变化起来
} - 执行原理:首先创建了循环变量,判断循环条件,如果条件满足,则执行一次循环体,并不会结束循环,会回过头,继续判断循环条件,满足的话,则再做一次
......
直到循环条件不满足false时,才会退出循环
宏观上看循环感觉一瞬间就结束了,但是微观上看其实是一次一次执行的 - 特殊: 死循环
- 有的时候真有可能需要使用死循环:永远不会停下来的循环
何时使用:不确定循环次数的时候
while(true){
循环体
}
- 有的时候真有可能需要使用死循环:永远不会停下来的循环
- 退出循环语句:
- break - 只能用在循环中,多半都是搭配死循环使用的;
- continue 退出当前次循环。
do while循环
-
语法:
var 变量=几;
do{
循环体;
变量的变化
}while(循环条件) -
面试题:while和do...while的区别?
只看第一次,如果条件都满足,则没区别
如果条件不满足,则while一次都不会执行,do...while至少会执行一次