2 JS基本语法
2.0 常量
常量也称字面量(literal),是一种固定值的表示方法,即字面上的意思,看见什么就能认出是什么,如数字、字符串、数组、json对象等类型的数据都有自己的字面量表示法。
-
数字字面量:常用的数学意义上的数字的表示法,书写时不需要添加任何特殊符号,直接写数字。
-
字符串字面量:字符串是人类说的语言、词语,包括各种数字、符号;由双引号对或单引号对包围;字符串内容被限定在同种引号之间,在字符串中某些字符需要用转义字符表示,如\n(换行)、\t(制表符)、"(引号)
console.log("我会说English,考试拿第1"); //直接显示引号里的内容
console.log(1); //表示字面量1
console.log("1"); //表示字符串1
console.log("这是\n一个引号\"和一个反斜杠\\"); //转义字符
2.1 变量
var message; //定义了一个名为message的变量
var message = "hi"; //定义message变量的同时赋值保存一个字符串值"hi"
var message = "hi", found = false, age = 29;
//使用一条语句,定义多个变量
-
变量(Variables)
- 相当于一个容器,可用来保存任何类型的数据
- ECMAScript的变量为
松散类型 - 变量名必须按照
标识符命名规范
-
变量的声明
- 即变量的定义,表示可以往里面存储数据
- 变量必须先声明(使用关键字
var)才能使用 - 用 var 声明一个未赋初值的变量,它的值会提前被设定为 undefined
- 若试图访问一个没有声明的变量会显示RefersnceErmor错误
- 对已经赋值的变量重新声明,该变量的值不会丢失
-
变量声明提升(hoisting)
- JS变量的另一特别之处是变量可以引用稍后声明,而不会引发异常
- 变量会被“举起”或提升到所有函数和语句之前,提升后的变量将返回undefined值,所以即使在使用或引用某个变量之后存在声明和初始化操作,仍将得到undefined值,但变量的提升,只提升定义,不提升赋值,相当于引用的时候只定义,没赋值,输出undefined
console.log(a); //先使用
var a = 125; //后定义
//相当于
var a; //先定义
console.log(a); //再使用
a = 125; //后赋值
2.2 数据类型
JS的数据类型是一种动态的数据类型,体现在变量上,变量的数据类型是随着内部存储数据的类型变化而变化的,变量的数据类型,就是它内部存储的数据的数据类型,且数据类型之间也可以进行相互转换
2.2.1 Undefined 类型
var message;
alert(message == undefined); //true
- Undefined 类型只有一个值,即在使用 var 声明变量但未对其加以初始化时, 其变量值就是 undefined
- 定义为undefined的变量与尚未定义的变量是不一样的
- 对未初始化和未声明的变量执行 typeof 操作符都会返回 undefined 值
2.2.2 Null 类型
var car = null;
alert(typeof car); // "object"
- Null 类型只有一个值,表示一个==空对象指针==,使用typeof操作符检测null值时会返回 "object"
- 如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null 而不是其他值,这样一来只要直接检查 null 值就可以知道相应的变量是否已经保存了一个对象的引用
- 实际上,undefined 值是派生自 null 值的
- ==可以通过将变量的值设置为 null 来清空变量==
2.2.3 Boolean 类型
var booleanValue = true;
alert(typeof booleanValue); // "Boolean"
布尔类型只有两个字面值 —— true 和 false,但ECMAScript中所有类型的值都有与这两个 Boolean 值等价的值。要将一个值转换为其对应的 Boolean 值,可以调用 转型函数 Boolean( ) ,如下例所示:
| 数据类型 | 转换为true的值 | 转换为false的值 |
|---|---|---|
| Boolean | true | false |
| String | 任何非空字符串 | "" (空字符串) |
| Number | 任何非零数字值(包括∞) | 0 和 NaN |
| Object | 任何对象 | null |
| Undefined | N/A(不适用) | undefined |
2.2.4 Number 类型
/*-------------- 整数字面量 -----------*/
//十进制:最基本的数值字面量格式,直接在代码中输入
console.log(100);
console.log(-12);
//八进制:前缀为0、0O、0o,若以0为前缀,超出取值范围会直接转换微十进制显示;若以0o/0O为前缀,超出取值范围直接显示报错
console.log(071); //表示为八进制数(71)
console.log(089); //表示为十进制数(89)
console.log(0o89); console.log(0O89); //显示出错
//十六进制:前缀为0x、0X,超出取值范围会直接报错,字母可大小写
console.log(0x5c);
console.log(0x5g); //显示出错
/*-------------- 浮点数字面量 -----------*/
//所有的浮点数都是以十进制表示
console.log(3.14159);
console.log(10.0); //被解析为整数10
console.log(0.618);
console.log(.618); //表示0.618
console.log(1.); //小数点后面没有数字会被解析为1
console.log(-.618); //表示-0.618
console.log(42356.89);
console.log(0.4235689e5);//e5表示×10^5,结果依然为42356.89
/*-------------- 特殊值 -----------*/
//无穷:计算机计算能力有限,如果大于或小于某个临界点,计算机没法算出具体数字,会直接输出是一个Infinity或-Infinity,无穷值无法继续参与下一次的计算
console.log(8.6e987654322344677807); //显示Infinity
console.log(-8.6e98765056760544387); //显示-Infinity
//NaN(not a number):不是一个数,说明这个数字已经没办法正常数值形式表示,不是一个正常意义的数字,但依然是一个数字字面量
console.log(0/0); //显示NaN
console.log(12/0); //显示NaN
- 进行算术计算时,所有八进制和十六进制表示的数值 都将被转换成十进制数值
- 浮点数值的最高精度是==17位小数==,但有些浮点数值计算会产生舍入误差的问题,这是使用基于IEEE754数值的浮点计算的通病,也会出现在其他语言上
2.2.5 String 类型
-
字符串:用于表示由零或多个16位Unicode字符组成的字符序列
var firstName = "Nicholas"; var lastName = 'Zakas'; var lastName = 'Nicholas"; // 语法错误(左右引号必须匹配) -
字符字面量:也叫转义序列,用于表示非打印字符或其他用途
var text = "This is the letter sigma: \u2764."; //该转义字符为❤ alert(text.length); //任何字符串的长度 可通过访问其length属性取得,输出28
字符串一旦创建,它们的值就不能改变,要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量,如下
var lang = "Java"; lang = lang + "Script"; /* 把lang的值重新定义为"Java"与"Script"的组合,即"JavaScript" */
2.2.6 Object 类型
2.2.7 数据转换
2.2.7.1 转Number
// Number():用于任何数据类型
var a = Number(null), //0
b = Number(undefined), //NaN
c = Number(true), //1
d = Number(false), //0
e = Number("-8"), //-8
f = Number("+8"), //8
g = Number("000011"), //11 (忽略0)
h = Number("0xf"), //15 (16转10进制)
i = Number(""), //0 (空白内容)
j = Number("12+3"), //NaN(存在符号)
k = Number("12-3"), //NaN(存在符号)
l = Number("a123"), //NaN(存在字母)
m = Number("12.."), //NaN(存在小数点)
n = Number(" 123"), //123(忽略空格)
o = Number("Hello world!"), //NaN(存在字母、间空格、符号)
// parseInt():仅能返回整数,丢失小数部分,指定基数,可进行进制转换
var A = parseInt("123blue"), //123
B = parseInt(""), //NaN
C = parseInt("Infinity"), //NaN
D = parseInt("12abc"), //12(忽略字符)
E = parseInt("a12bc"), //NaN(头部非数字,识别出错)
F = parseInt("0xAF", 16), //175
G = parseInt("AF", 16), //175
H = parseInt("AF"), //NaN(指定基数会出错)
I = parseInt("10", 2), //2 (按二进制解析)
J = parseInt("10", 8), //8 (按八进制解析)
K = parseInt("10", 10), //10 (按十进制解析)
L = parseInt("10", 16), //16 (按十六进制解析)
M = parseInt(22.5), //22
N = parseInt(5.2e10); //5
// parseFloat():将字符串转为带小数的浮点数
var A1 = parseFloat("12.23"), //12.23
A2 = parseFloat("12.23.34"),//12.23
A3 = parseFloat("12.23AAA"),//12.23(忽略尾部字符)
A4 = parseFloat("12.3+123");//12.3(忽略尾部字符)
2.2.7.2 转String
// console.log():null与undefined类型直接用控制台输出变成String类型
console.log(null); //"null"
console.log("Hello"+null); //"Hellonull"
console.log(undefined); //"undefined"
console.log("Hello"+undefined); //"Helloundefined"
// toString()
var a = true;
var aStr = a.toSting(); //"true"
var b = 11;
var bStr = b.toSting(); //"11"
// String():能够将任何类型的值转换为字符串
var W = 10;
var X = true;
var Y = null;
var Z; //未定义值 undefined
alert(String(W)); //"10"
alert(String(X)); //"true"
alert(String(Y)); //"null"
alert(String(Z)); //"undefined"
由于 null 和 undefined 没有 toString() 方法,所以只能使用String()函数
2.2.7.3 转Boolean
// Boolean():能将大多数类型的值转换为布尔值
// 绝大多数转成布尔值,结果都为true
// 以下6种情况转为boolean,结果为false
console.log(Boolean(0)); //false
console.1og(Boolean("")); //false
console.1og(Boolean(false)); //false
console.1og(Boolean(NaN)); //false
console.1og(Boolean(undefined));//false
console.log(Boolean(null)); //false
2.3 操作符
运算符(Operators),也称操作符,是发起运算的最简单形式
2.3.1 一元操作符
- 自加(
++)自减(--):放于前“先±1再取值”,放于后“先取值再±1” - 一元加(
+)减(-):相当于正负号
2.3.2 加性操作符
- 加法(
+) - 减法(
-)
+可以作连接符进行字符串操作:("OX"+"456" → OX456)
2.3.3 乘性操作符
- 乘法(
*) - 除法(
/) - 求模取余(
%)
2.3.4 赋值操作符
- 赋值运算符(
=):把右侧的值赋给左侧的变量 - 复合赋值运算符:
加等+=减等-=乘等*=除等/=余等%=左移等<<=有符号右移等>>=无符号右移等>>>=
var num = 10;
num = num + 10;
num += 10; // 等价于上一条语句,复合赋值仅作简化操作
复合赋值运算时,等号后面的部分是一个整体,如
y*=x-3——>y=y*(x-3)
2.3.5 比较操作符
- 关系操作符(
><>=<=) - 相等(
==)不相等(!=):只比较数值,不比较类型,比较前自动统一类型 - 全等(
===)不全等(!==):数值和类型都要比较
所有的比较操作符都会返回一个布尔值(true 与 false)
关系运算符不能连用。(例如 1 <= num <= 5 会存在语法错误)
2.3.6 位操作符
- 按位与(
~) - 按位与(
&) - 按位或(
|) - 按位异或(
^) - 左移(
<<) - 有符号右移(
>>) - 无符号右移(
>>>)
2.3.7 布尔操作符
- 逻辑非(
!):有非则反 - 逻辑与(
&&):两真才真 - 逻辑或(
||):有真就真
对于 A&&B,当 A 被认定为 false,就不会再进行 B 的操作了
2.3.8 条件操作符
// (判断条件)? 满足输出 : 不满足输出
var max = (num1 > num2) ? num1 : num2;
2.3.9 逗号操作符
使用逗号(,)操作符可以在一条语句中执行多个操作。
var num1=1, num2=2, num3=3; // 声明多个变量
var num = (5,1,4,8,0); // num的值为0(多赋值时会返回表达式中的最后一项)
2.3.X 运算优先级
从高到低:算术操作符 → 比较操作符 → 逻辑操作符 → "="赋值符号
同级运算:按从左到右次序进行,多层括号由里向外
2.3.Ⅺ 隐式转换
数字与纯数字字符串字符串之间进行运算,==除了+号之外==,使用其他运算符会自动将字符串转成数字,其他数据类型参与任何数学运算都会被隐式转换,这个过程是私下进行,不需要使用parseInt等方法
console.log(12+"2"); //结果为122
console.log(12-"2"); //结果为10
console.log(12*"2"); //结果为24
console.log(12/"2"); //结果为6
console.log(12%"2"); //结果为0
console.log("12"%"2"); //结果为122
//其他隐式转换
- 转换为0 : "", null, false
- 转换为1 : true
- 转换为NaN : "非空字符串", undefined, NaN
- 转换为Infinity : 情况由具体决定
2.4 语句
2.4.1 if-else语句
==条件判断语句==,判断condition返回的布尔值,若是true执行statement1,若是false则执行statement2。
// if (condition) statement1 else statement2
if (i > 25)
alert("Greater than 25."); // 单行语句
else {
alert("Less than or equal to 25."); // 代码块{}中的语句
}
// if (condition1) statement1 else if (condition2) statement2 else statement3
if (i > 25) {
alert("Greater than 25.");
} else if (i < 0) { //多层嵌套 条件判断
alert("Less than 0.");
} else {
alert("Between 0 and 25, inclusive.");
}
2.4.2 do-while 语句
一种==后测试循环语句==,即先执行一次statement后,再判断expression,若返回false,则重新执行一次statement,直到返回true,才能往下继续执行。
// do {statement} while (expression);
var i = 0;
do {
i += 2;
} while (i < 10);
alert(i);
2.4.3 while 语句
一种==前测试循环语句==,即先判断expression,若返回true则执行一次statement,执行完后重新判断expression,若为false则跳过statement,再往下进行。
// while (expression) statement
var count = 10;
var i = 0;
while (i < count) {
alert(i);
i++;
}
2.4.4 for 语句
另一种==前测试循环语句==,先执行initialization来设定一个初始值,再判断expression,若返回true则去执行statement,执行完statement再去执行post-loop-expression,然后重新判断expression,直到返回false才跳出循环,往下执行。
// for (initialization; expression; post-loop-expression) statement
var count = 10;
for (var i = 0; i < count; i++){
alert(i);
} // 与前面while代码块执行的功能相同
- for循环是while循环的另一种表达,两者作用相同;
- initialization可以不使用var关键字而在外部去定义;
- 由于ECMAScript中不存在块级作用域,因此在循环内部定义的变量也可以在外部被访问到;
- for 语句中的初始化表达式、控制表达式和循环后表达式都是可选(可省略)的,如 for ( , , )。
2.4.5 switch 语句
另一种==条件判断分支语句==,设置一个变量 i,让其值与结构中的每个情况 case 值做比较,若存在匹配,则执行该 case 关联的代码块,执行完后使用 break 来跳出此 case同时阻止继续运行下一个 case,若无对应值时直接执行 default 关联的代码块。
// switch (expression) {case A: statet1 break; case B: state2 break; default: state3}
switch (i) {
case 25:
alert("25");
break;
case 35:
alert("35");
break;
case 45:
alert("45");
break;
default:
alert("Other");
}
- expression可以使用任何数据类型,无论是字符串或是对象;
- 每个 case 的值不一定是常量,可以是变量,甚至是表达式。
2.4.6 break 和 continue 语句
一种==断点语句==,用于在循环中精确地控制代码的执行。
var num = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
break; //立即跳出循环,强制继续执行循环后面的语句
}
num++;
}
alert(num); // 输出4
var num = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
continue; //结束本次循环后会从循环的顶部重新执行
}
num++;
}
alert(num); // 输出8
2.4.7 label 语句
一种==标签语句==,在代码中添加标签,标签可以在将来由 break 或 continue 语句引用。一般都要与 for 语句等循环语句配合使用,从而返回代码中特定的位置。
// label: statement
var num = 0;
outermost:
for (var i=0; i < 10; i++) {
for (var j=0; j < 10; j++) {
if (i == 5 && j == 5) {
break outermost; /* 退出内部循环(使用变量j循环),也退出外部循环(使用变量i循环)*/
}
num++;
}
}
alert(num); //55
var num = 0;
outermost:
for (var i=0; i < 10; i++) {
for (var j=0; j < 10; j++) {
if (i == 5 && j == 5) {
continue outermost; /* 强制继续执行循环 —— 退出内部循环,执行外部循环 */
}
num++;
}
}
alert(num); //95
2.4.8 for-in 语句
一种精准的==迭代语句==,用来枚举对象的属性。
// for (property in expression) statement
for (var propName in window) {
document.write(propName);
}
/*
这里显示了 BOM 中 window 对象的所有属性(变量 in 对象)。即每次执行循环时,都会将 window 对象中存在的一个属性名赋值给变量 propName 。这个过程会一直持续到对象中的所有属性都被枚举一遍为止。
*/
ECMAScript对象的属性没有顺序,因此不可预测的。所有属性都会被返回一次,但返回的先后次序可能会因浏览器而异。
如果要迭代的对象是null或者是undefined,那么会抛出异常。
2.4.9 with 语句
将代码的作用域设置到一个特定的对象中,目的主要是==为了简化多次编写同一个对象的工作==。
// with (expression) statement;
原程序 //(包含了多个location对象)
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;
改为
with (location) { // 简化
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}
大量使用 with 语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用 with 语句。
2.5 函数
函数可以封装任意多条语句,在任何地方在、任何时候需要调用时执行。函数在定义时不必指定是否返回值,但可通过 return 语句来实现值的返回。
function functionName (arg0, arg1, ...) {statements}
function sayHi(name, message) {
alert("Hello " + name + "," + message);
}
sayHi("Nicholas", "how are you today?");
/* 这个函数的输出结果是 "Hello Nicholas,how are you today?" */
function sum (num1, num2) {return num1 + num2;}
var result = sum(5, 10);
function sum(num1, num2) {
return num1 + num2; // 执行完return语句之后停止并立即退出
alert("Hello world"); // 永远不会执行
}
return语句也可以不带有任何返回值(
return;),函数在停止执行后将返回 undefined值,但推荐做法是要么让函数始终都返回一个值,要么永远都不要返回值