从零开始的JS生活(一)——JS简介、变量及基本结构
本K在经过三个静态站制作的狂风暴雨之后,终于开始了JavaScript的学习。作为一只从来没有正儿八经接受过计算机语言的小白,居然能够跟上浩哥的课程进度,我的内心都被我的才智震惊到了,果然本K是天生丽质难自弃,天生我材必有用哇,哦呵呵~
咳咳,废话不多说,咱们来开始我们的JS小课堂,希望能够帮助到跟我一样的第一次接受计算机语言的同志们。
一、什么是JS。
JavaScript,简称JS,它是一种基于浏览器的、基于对象的、用于事件驱动的脚本语言。简单来说,JS就是用来实现html页面上的一些动态效果的语言。它的作用有很多,它可以进行表单的验证,可以添加页面的动态效果,可以动态更改页面的内容,也可以通过Ajax来实现页面的局部更新。
二、JS的组成部分。
JS主要有三大部分组成。
1、ECMAScript语法标准,简称ES标准,它规范了JS中的语法、变量和数据类型、运算符、逻辑控制语句等重要内容。
2、BOM,浏览器对象模型,包括history(历史)、document(文档)、location(地址)等浏览器相关的重要信息。
3、DOM,文档对象模型,它的重要内容可以概括为“节点”,节点可以是html中的任意一个标签,像是head,body就是html文档中的两个节点,两者以下的所有分支都可以形成非常具有层次性的节点层。
三、JS的基本结构与使用方式
1、基本结构
我们大多数情况下见到的是在html文档中直接插入的JS代码,结构如下图↓
2、使用方式
JS的使用方式有三种,在这一点上和CSS的使用方式大致相同,但在某些细节上有所不同。
方式一:HTML标签中内嵌JS(不推荐!)
方式二:HTML页面中直接使用
方式三:引用外部JS文件(与CSS外部文件引用相区分!)
四、变量
1、变量声明的写法
1.1 先声明变量在赋值
var width; width=5;
使用var声明的变量,只在当前函数作用域有效(提倡使用)
1.2 不声明,直接赋值(默认全局变量)
width=5;
不使用var,直接赋值生成的变量,默认为全局变量,整个JS文件有效
1.3 同时声明和赋值变量
var catName="ppap";
var x,y,z=10;
同一声明语句同时生命多个变量,变量之间用英文逗号分隔。但赋值需要单独赋,例如上式中,只有z赋为1,x,y为undefined(未定义)
【注意事项】
① JS中所有变量类型声明,均使用var关键字。变量的具体数据类型,取决于给变量赋值的执行;
② 同一变量,可以在多次不同赋值时,修改变量的数据类型:
var width=10;//width 为整形变量;
width="哈哈";// width 被改为字符串类型;
③ 变量可以使用var声明,也可以省略var。区别:不使用var,默认为全局变量;
④ 同一变量名,可以多次用var声明,但是并没有任何含义,也不会报错。第二次之后的声明,只会被理解为赋值;
⑤ JS末尾分号可以省略,但不建议省略。
2、变量的命名规则
2.1 变量名只能由字母,数字,下划线,$组成;
2.2 开头不能为数字;
2.3 变量区分大小写,大写字母与小写字母为不同变量。
3、变量名命名要符合(小)驼峰法则
变量开头为小写,之后每个单词首字母大写;或者单词之间用下划线分割。
4、JS中的变量的数据类型
4.1 Undefined:未定义,用var声明的变量,没有进行初始化赋值;
4.2 Null:表示为空的引用,例如空对象、空数组;
4.3 Boolean:真假,可选值true/false;
4.4 Number:数值类型,可以是小数,也可以是整数;
4.5 String:字符串,用双引号""或单引号''包裹的内容,成为字符串;
4.6 Object:(复杂数据类型)。
5、常用的数值函数
5.1 isNaN():用于判断一个变量或常量是否为为NaN(非数值)
使用isNaN判断时,会尝试使用Number()函数进行转换,如果能转换为数字,则不是非数值,则结果为false;
"111" 纯数字字符串,false
""空字符串,false
"1a" 包含其他字符的字符串,true
true/false 布尔类型,false
5.2 Number():
将其他类型转换为数值类型
【字符串类型转数值】
>>> 字符串为纯数字字符串会转为对应的数字,例如"111"会转换为111
>>> 字符串为空字符串时,会转为0 ,例如 ""会转换为0
>>> 字符串包含其他非数字字符时,不能转换 ,例如"111a"会转换为NaN
【布尔类型转换值】
true —— 1 flase —— 0
【null/undefined转数值】
null —— 0 undefined —— NaN
【object转数值】
先调用ValueOf方法,确定函数是否有返回值,再根据上述各种情况判断。
5.3 parseInt():
将字符串转换为数值类型
>>> "" —— 不能转,结果为NaN
>>> 纯数字字符串 —— 能转,但是小数转化时会抹掉小数点后面的数字,不会进行四舍五入
>>> 包含其他字符的字符串 —— 会截取第一个非数值字符前的数值部分 "123a45"——123 "a123"——NaN
>>> parseInt只能转string类型,布尔、null、undefined均为NaN
5.4 parseFloat():
将字符串转换为数值
>>> 使用方式同parseInt,但是当转换小数字符串时,保留小数点;转化整数字符串时,保留整数。
5.5 typeOf():
用来检测变量数据类型
未定义——Undefined;字符串——string;true/false——Boolean;数值——Number;对象/null——Object;函数——function。
五、常用输出语句
1、 document.write("")
输出语句,将write的()中的内容打印在浏览器屏幕上;
使用时注意:除变量/常量以外的任何内容,打印时必须放到""中。变量/常量必须放到""外。
打印的内容有多部分组成时,之间用+链接;
例如:document.write("左手中的纸牌:"+left+"<br/>")
2、 alert();
弹窗警告,()中的使用方式同上。
六、运算符
1、算术运算(单目运算符)
+ :加 两种作用:
连接字符串(当加号两边有任意一边为非数字时,链接之后结果为字符串)
进行运算(当加号两边均为数字时)
- :减
* :乘
/ :除 除出来是几就是几
% :取余
++ :自增 在原有基础上加1
-- :自减 在原有基础上减1
n++ ++n的异同
不同点:
n++:先使用n的值进行计算,然后再把n+1 ;
++n:先把n的值+1,然后再用n+1以后的值运算。
相同点
不论n++还是++n,在执行完代码以后,均会把n+1。
2、赋值运算
= :赋值
+=:a+=5; 相当于a=a+5;
-= :a-=5;相当于a=a-5;
但是,前者的执行效率要比后者快
*=
/=
%=
3、关系运算
==:等于,类型相同的时候,同===;类型不同时,尝试将等式两边转为数字,再判断。
NaN == NaN false; null==undefined true。
===:严格等于,类型不同,直接返回false;类型相同,在进行下一步判断。
null===undefined false。
!=:不等于
>=:大于等于
<=:小于等于
4、条件运算(多目运算)
a>b?true:false
有两个关键符号: ? 和 :
当?前面的部分运算结果为true时执行:前面的代码;
当?前面的部分运算结果为false时执行:后面的代码。
多目运算符可以多层嵌套,例如:
var num = 5 ;
document.write(num>5?"呵呵":(num==5?"哈哈":"嗷嗷"));
5、逻辑运算符
&&逻辑与运算符
||逻辑或运算符
!非
6、运算符的优先级(优先级从高到低)
()
++ -- !
* / %
+ -
> < >= <=
== !=
&&
||
各种赋值
七、分支结构
1、if-else结构
1.1 结构写法
if(条件){
语句
}else{
语句
}
1.2 if()中的表达式,运算之后的结果应该为:
① Boolean:true 真/false 假;
② String:非空字符串为真/空字符串为假;
③ Null/NaN/Undefined:全为假;
④ object:全为真;
⑤ Number:0为假/其他全部为真;
1.3 else{}结构,可以根据具体情况省略。
2、多重if、阶梯if、if-else-if 结构 (提倡)
2.1 结构写法
if(条件一){
// 条件一成立
}else if(条件二){
// 条件一不成立&&条件二成立
// else-if部分可以有n多个
}else{
// 条件一不成立&&条件二不成立
}
2.2 多重if结构中各个判断条件是互斥的!只能选择其中一条路。
2.3 if/else的{}可以省略,但是一般不提倡;
如果省略{}、则if/else结构包含的代码,仅为其后最近的一行(分号结束);
如果省略{}、则else结构永远输入其前方最近的一个结构。
3、嵌套if结构(不提倡)
3.1 结构写法
if(条件一){
//条件一成立
if(条件二){
//条件一成立&&条件二成立
}else{
//条件一成立&&条件二不成立
}
}else{
//条件一不成立
}
3.2 if结构可以多重嵌套,但是原则上不超过3层
4、switch-case结构
4.1 结构写法
swith(表达式){
case 常量表达式一:
语句;
break;
case 常量表达式二;
语句;
break;
......
default:
语句;
break;
}
4.2 注意事项
① switch()中的表达式,以及每个case之后的表达式,可以为任何JS支持的数据类型,但不能是对象和数组;
② case后面的所有常量表达式必须各不相同,否则只会执行第一个;
③ case后的常量可以是任何数据类型;同一个switch结构的不同case可以是多种不同的数据类型;
④ switch结构在进行判断的时候,采取的是全等判断===;
⑤ break的作用:执行完case代码后,跳出当前的switch结构;
缺少break的后果:从正确的case项开始,依次执行所有的case和default;(原因 -> ⑥)
⑥ switch结构在判断时,当遇到正确的case项后,将会不在判断后续项目,依次往下执行;
⑦ switch结构的执行速率要快于多重if结构,在多路分支时,可优先考虑使用switch结构。
八、循环结构
1、循环结构的步骤
声明循环变量→判断循环条件→执行循环体(while的{}中的所有代码)操作→更新循环变量(缺失会导致死循环)→然后循环执行前2-4条
2、JS中循环条件支持的数据类型
① Boolean:true 真/false 假;
② String:非空字符串为真/空字符串为假;
③ Null/NaN/Undefined:全为假;
④ object:全为真;
⑤ Number:0为假/其他全部为真;
3、循环特点
while循环特点:先判断,在执行;
do-while循环特点:先执行,后判断;即便初始条件不成立,do-while循环也至少执行一次。
4、for循环
4.1 三个循环表达式:<初始化循环变量>;<判断循环条件>;<循环变量更新>,各个之间用;分割;
for循环三个条件都可以省略,两个;缺一不可。
4.2 for循环特点:先判断在执行。
4.3 for循环三个表达式均可以由多部分组成,之间用,分割;但是第二部分判断条件需要用&&链接,最终结果需要为真/假。
九、嵌套循环
1、循环控制语句
1.1 break 终止本层循环,继续执行循环后面的语句
当循环有多层时,break只会跳过一层循环;
1.2 continue 跳过本次循环,继续执行下一次循环
对于for循环,continue执行后,继续执行循环变量更新语句(n++);
对于while、do while,continue执行后,继续执行循环条件判断;所以使用这两个循环时,必须注意:continue一定要在n++之后使用。
2、嵌套循环特点
外层循环控制行数,内层循环控制每行元素个数
3、图形题思路
3.1 确定图形一共几行,即为外层的循环次数;
3.2 确定每行有几种元素,代表有几个内层循环;
3.3 确定每种元素的个数,即为每个内层循环的次数;
Tips:通常找出每种元素个数与行号的关系式,即为当前内层循环的最大值;(从1开始循环)
①判断是否为一个数字:Number(num)不为NaN,说明为数字
②判断一个数字是否为正数:Number(num)>0
③判断一个数字是否为整数:parseInt(num)==parseFloat(num)
十、函数
1、函数定义的三个部分
函数名 function
参数列表: 有参函数;无参函数。
函数体
2、函数的声明及调用
2.1 函数的声明格式:
function 函数名(参数1,参数2,参数3){
//函数体
return 结果;
}
函数调用的格式:
直接调用 : 函数名(参数1的值,参数2的值,......);
事件调用 : 事件名=函数名();
2.2 函数声明的几点强调:
①函数名的命名必须符合小驼峰法则(首字母小写,之后每个单词首字母大写);
②参数列表,可以有参数、可以无参数,分别叫做有参函数、无参函数;
③声明函数时的参数列表称为"形参列表"(变量的名);调用函数时的参数列表称为"实参列表"(变量的值);{函数中实际有效的参数取决于实参的赋值,未被赋值的形参将为undefined};
④函数如果需要返回值,可用return返回结果。调用函数时,使用 var 变量名 = 函数名(); 的方式,接受返回结果;如果函数没有返回值,则接受的结果为Undefined。
⑤函数中变量的作用域:在函数中,使用var声明的变量,默认为函数局部变量,只在函数内容能用(不使用var声明的变量,默认为全局变量(函数中的全局变量,必须在函数调用后才能使用));函数的形参列表,为函数局部变量,只在函数内部能用;
⑥函数声明与函数调用没有先后之分。即调用语句可写在声明语句之前。
JS中代码运行,会先进行检查、装载,即声明变量、函数等操作;然后再进入执行阶段,(变量的赋值等属于执行阶段)。所以函数的声明属于检查装载阶段,函数的调用属于执行阶段。所以,函数的调用语句卸载函数的声明语句之前,并没有任何关系。
//栗子如下↓
console.log(num);
var num = 10;
funN();
function funcN(){}
顺序为:
————检查装载阶段————
var num ; //声明变量
function funcN(){} //声明函数
————执行阶段————
console.log(num);
num = 10;
funN(); //执行函数的{}中代码
3、匿名函数的声明和调用
3.1 声明一个匿名函数,直接赋给某个事件;
window.onload = function (){}
3.2 使用函数表达式声明匿名函数;
var fun = function(){} //声明函数表达式
fun(); //调用函数表达式
>>>使用匿名函数表达式,则调用语句必须在声明语句之后,否则报错(对比常规函数声明与调用区别?)
3.3 使用自执行函数声明并直接调用匿名函数;
① !function(参数1){}(参数1的值);
使用任意运算符开头,一般使用!
② (function(){}());
使用()将匿名函数及之后的括号包裹
③ (function(){})();
使用()只包裹匿名函数表达式
三种写法的特点:
①结构清晰,开头加!,结尾加(),不容易乱,推荐使用;
②可以表明匿名函数与之后的小括号为一个整体,官方推荐使用;
③无法表明函数与之后()为一个整体,不推荐使用。
4、函数内部重要属性
4.1 arguments对象
①作用:用于保存调用函数式所赋值的实参列表。
>>>当调用函数并使用实参赋值时,实际上参数已经保存到arguments数组中,即使没有形参,也可以使用arguments[n]的形式调用参数。
②arguments数组的个数取决于实参列表,与形参无关(顺序,从0开始);但当第n个位置的形参、实参、arguments都存在时,形参与arguments是同步的。(即在函数中修改其中一个的值,另一个会同步变化)
③arguments.callee时arguments的重要属性,用于返回arguments所在函数的引用(引用:地址);可以调用自身函数执行;在函数内部调用函数自身的写法被称为“递归”,所以arguments.callee()是递归调用时常用的方法。
4.2 this
函数调用语句所在的作用域,即谁调用函数,this指向谁。