《Javascript 高级程序设计(第三版)》通读后的总结笔记(二)

239 阅读12分钟

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
  1. Undefined 类型只有一个值,即在使用 var 声明变量但未对其加以初始化时, 其变量值就是 undefined
  2. 定义为undefined的变量与尚未定义的变量是不一样的
  3. 对未初始化和未声明的变量执行 typeof 操作符都会返回 undefined 值

2.2.2 Null 类型

var car = null;
alert(typeof car); // "object"
  1. Null 类型只有一个值,表示一个==空对象指针==,使用typeof操作符检测null值时会返回 "object"
  2. 如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null 而不是其他值,这样一来只要直接检查 null 值就可以知道相应的变量是否已经保存了一个对象的引用
  3. 实际上,undefined 值是派生自 null 值的
  4. ==可以通过将变量的值设置为 null 来清空变量==

2.2.3 Boolean 类型

var booleanValue = true;
alert(typeof booleanValue);		// "Boolean"

布尔类型只有两个字面值 —— true 和 false,但ECMAScript中所有类型的值都有与这两个 Boolean 值等价的值。要将一个值转换为其对应的 Boolean 值,可以调用 转型函数 Boolean( ) ,如下例所示:

数据类型转换为true的值转换为false的值
Booleantruefalse
String任何非空字符串"" (空字符串)
Number任何非零数字值(包括∞)0 和 NaN
Object任何对象null
UndefinedN/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代码块执行的功能相同
  1. for循环是while循环的另一种表达,两者作用相同;
  2. initialization可以不使用var关键字而在外部去定义;
  3. 由于ECMAScript中不存在块级作用域,因此在循环内部定义的变量也可以在外部被访问到;
  4. 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");
}
  1. expression可以使用任何数据类型,无论是字符串或是对象;
  2. 每个 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值,但推荐做法是要么让函数始终都返回一个值,要么永远都不要返回值