本章内容
- 语法
- 数据类型
- 流控制语句
- 理解函数
1 语法
1.1 区分大小写
ECMAScript中的一切(变量 、函数和操作符)都区分大小写。
1.2 标识符
标识符,就是指变量、函数、属性的名字,或者函数的参数。
标识符的格式
- 第一个字符必须是字母、下划线(_)或者一个美元的符号($)
- 其他字符可以是字母、下划线、美元符号或数字
标识符的格式采用驼峰大小写格式,也就是说第一个字母小写,剩下的每个有意义的单词的首字母大写,例如:
firstSecond
myCar
doSomethingImportant
注意,不能把关键字、保留字、true、false和null用作标识符
1.3 注释
ECMAScript使用C风格的注释,包括单行注释和块级注释。
单行注释
// 单行注释
块级注释
/*
* 这是一行
* [块级]注释
*/
当然,目前IDE注释都很方便,了解即可。
1.4 严格模式
JavaScript 严格模式(strict mode)即在严格的条件下运行
"use strict" 的目的是指定代码在严格条件下执行
"use strict";
x = 3.14; // 报错 (x 未定义)
"use strict";
myFunction();
function myFunction() {
y = 3.14; // 报错 (y 未定义)
}
x = 3.14; // 不报错
myFunction();
function myFunction() {
"use strict";
y = 3.14; // 报错 (y 未定义)
}
为什么使用严格模式:
- 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
- 消除代码运行的一些不安全之处,保证代码运行的安全;
- 提高编译器效率,增加运行速度;
- 为未来新版本的Javascript做好铺垫。
1.5 语句
ECMAScript中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾,如下图所示
var sum = a + b //即使没有分号,也是有效的语句
var diff = a - b; //有效语句
这本书上说,建议任何时候都不要省略分号。因为加上这个分号可以避免很多错误,开发人员也可以放心地来压缩代码。
另外,用分号一定程度上可以提高性能,因为解析器就不需要再花时间推测该在哪里插入分号了。
还有,使用{}来将多条语句组合到一个代码块中。
在控制语句中,使用代码块可以让编码意图更加清晰,而且也能降低修改代码时出错的几率。
2 关键字和保留字
abstract
arguments
boolean
break
byte
case
catch
char
class*
const
continue
debugger
default
delete
do
double
else
enum*
eval
export*
extends*
false
final
finally
float
for
function
goto
if
implements
import*
in
instanceof
int
interface
let
long
native
new
null
package
private
protected
public
return
short
static
super*
switch
synchronized
this
throw
throws
transient
true
try
typeof
var
void
volatile
while
with
yield
反正,写代码的时候,如果用错标识符,IDE会提醒你的,了解就好,😱不需要背下来。
3 变量
ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。
4 数据类型
ECMAScript中有5种简单数据类型(基本数据类型):Undefined、Null、Number和String。还有1种复杂数据类型——Object,它的本质上是由一组无序的键值对组成的。
ECMAScript不支持任何床见自定义类型的机制,而所有值最终都是上述6种数据类型之一。由于ECMAScrip数据类型具有动态性,因此的确没有再定义其他数据类型的必要了。
这里说的动态性,指的是数据类型可以扩展出任何类型,如object,可以动态添加属性与方法。
4.1 typeof操作符
鉴于ECMAScript是松散类型的,因此需要来检测给定的变量的数据类型,typeof就是负责提供这方面信息的操作符。对一个值使用typeof操作符可能返回下列某个字符串:
- "undefined"——这个值未定义;
- "boolean"——这个值是布尔值;
- "string"——这个值是字符串;
- "number"——这个值是数值;
- "object"——这个值是对象或null;
- "function"——这个值是函数。
例子:
var message = "some string";
alert(typeof message);//"string"
alert(typeof(message));//"string"
alert(typeof 95);//"number"
这几个例子说明,typeof操作符的操作数可以是变量(message),也可以是数值字面量。注意,typeof是一个操作符而不是函数,因此例子中的圆括号尽管可以使用,但不是必须的。
4.2 Undefined类型
Undefined类型只有一个值,即特殊的undefined。在使用var声明变量但未对其初始化时,这个变量的值就是undefined,例如:
var message;
alert(message == undefined);//true
4.3 Null类型
Null类是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值时会返回"object"的原因。
如果定义的变量准被在将来用于保存对象,那么最好将该变量初始化为null。这样一来,只要直接检查null值就可以知道相应的变量时候已经保存了一个对象的引用了。
4.4 Boolean类型
该类型只有两个字面值:true和false。这两个值与数字值不是同一回事,因此true不一定等于1,而false也不一定等于0。
虽然Boolean类型的字面值只有两个,但ECMAScript中所有类型的值都有与这两个Boolean值等价的值,可以调用转类型函数Boolean()。
下表给出了各种数据类型及其对应的转换规则。
数据类型 | 转换为true值 | 转换为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | 空字符串("") |
Number | 任何非零数字值(包括无穷大或无穷小) | 0和NaN(不是数字) |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
这些转换规则在流控制语句(如if语句)有很重要的作用
4.5 Number类型
这种类型使用IEEE754格式来表示整数和浮点数值(浮点数值在某些语言中也被称为双精度数值)。
最基本的数值字面量格式是十进制。
除了以十进制表示外,整数还可以通过八进制(以8为基数)</span>或十六进制(以16进制)关于二进制,八进制,十进制和十六进制的说明
其中,八进制字面值的第一位必须是0,然后是八进制数值序列(0~7)。如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析。例子:
var octalNum1 = 070;//八进制的56
var octalNum2 = 079;//无效的八进制数值——解析为79
var octalNum3 = 08;//无效的八进制数值——解析为8
八进制字面量在严格模式下是无效的,会导致支持的JavaScript引擎抛出错误。
十六进制字面值的前两位必须是0x,后面跟任何十六进制数值(09及AF)。其中,字母A~F可以大写,也可以小写。例子:
var hexNum1 = 0xA;//十六进制的10
var hexNum2 = 0x1f;//十六进制的31
在进行算数计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值。
4.5.1 浮点数值
所谓浮点数值,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。例子:
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1;//有效,但不推荐
由于保存浮点数值需要的内存空间是保存整数值的两倍,因此ECMAScript会不失时机地将浮点数值转换为整数值。例子:
var floatNum1 = 1.;//小数点后面没有数字——解析为1
var floatNum2 = 10.0;//整数——解析为10
对于那些极大或者极小的数值,可以用e表示法(科学计数法)。用e表示法表示的数值等于e前面的数值乘以10的指数次幂。例子:
var floatNum1 = 3.125e7;//等于31250000
var floatNum2 = 3.125E7;//e不区分大小写
var floatNum3 = 3e-7;//等于0.0000003
浮点数值的最高精度是17位小数,但是在进行算术计算时其精确度远远不如整数。
var a = 0.1;
var b = 0.2;
if (a + b == 0.3) {//不要做这样的测试,因为你不能成功的
alert("You got 0.3");
}
console.log(a + b);//0.30000000000000004
4.5.2 数值范围
由于内存限制,ECMAScript不能保存世界上所有的数值。ECMAScript能够表示的最小数值保存在Number.MIN_VALUE中;能够表示的最大数值保存在Number.MAX_VALUE中。如果某次计算的寄过得到了一个超出ECMAScript数值范围的值,那么这个数值将被自动转换成特殊的Infinity值。具体来说,如果这个值是负数,则会转换成-Infinity(负无穷),反之,则会被转成Infinity(正无穷)。
如上所述,如果某次计算返回了正或负的Infinity值,那么该值将无法参与下一次的计算。可以通过isFinite()来判断,例子:
var result = Number.MAX_VALUE + Number.MAX_VALUE;
console.log(isFinite(result));//false
4.5.3 NaN
这个就是Not a Number,翻译过来就是不是数值,在ECMAScript中,它是一个特殊的数值,表示本来应该返回数值的操作,结果么有返回数值,防止抛出异常。
- NaN与任何值都不相等,包括它本身
- 任何涉及到与NaN的操作,都会返回NaN。
增对这两个特点,ECMAScript定义了isNaN()函数。这个函数可以帮我们确定参数是否“不是数值”。即,任何不能被转换为数值的参数都会导致这个函数返回true。例子:
console.log(isNaN(NaN)); //true
console.log(isNaN(10)); //false
console.log(isNaN("10")); //false(可以被转换成数值10)
console.log(isNaN("blue")); //true(不能被转换成数值)
console.log(isNaN(true));//false(可以被转换成数值1)
isNaN()也适用于对像。在基于对象调用isNaN()函数时,会首先调用对象的valueOf()方法,然后确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用toString()方法,再测试返回值。
4.5.4 数值转换
Number()、parseInt()和parseFloat()这三个函数可以把非数值转换为数值。
Number(),即转型函数,它可以用于任何数据类型,它的转换规则如下:
- 如果是Boolean值,true和false将分别转换为1和0.
- 如果是数值,只是简单的输入和输出。
- 如果是null值,返回0。
- 如果是undefined,返回NaN。
- 如果是字符串,遵循以下规则:
1,如果字符串中只包含数字(包括前面带上加号或减号),则将其转换为十进制数值。
2,如果字符串是有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值。
3,如果字符串中是有效的十六进制格式,例如“0xf”,则将其转换为对应的十进制数值。
4,如果字符串是空的,则将其转换为0。
5,如果字符串包含上述格式之外的字符,则将其转换为NaN。
*如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再依照前面的规则转换返回的字符串的值。
例子:
console.log(Number(true));//1
console.log(Number(false));//0
console.log(Number(1));//1
console.log(Number(null));//0
console.log(Number(undefined));//NaN
console.log(Number("1"));//1
console.log(Number("00001"));//1
console.log(Number("1.1"));//1.1
console.log(Number("00001.1"));//1.1
console.log(Number("0xf"));//15
console.log(Number(""));//0
console.log(Number("1abc1.1"));//NaN
parseInt(),它在转字符串时,更多的时看其是否符合数值模式。他会忽略字符串前面的空格,只倒找到第一个非空格字符。如果第一个字符不是数字字符或者正负号,它就会返回NaN;也就是说parseInt()转换空字符串会返回NaN(Number()会返回0)。如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有的后续字符或者遇到了一个非数字字符。例如,“123木头人”会被转换为123。类似的“123.5”会被转换为123,因为小数点不是有效的数字字符。
另外,如果字符串以“0x”开头且后面跟数字字符,就会将其当成一个十六进制的整数;如果字符串以“0”开头且后面跟数字字符,就会将其当成一个八进制数来解析。
例子:
console.log(parseInt(""));//NaN
console.log(parseInt("123木头人"));//123
console.log(parseInt("123.5"));//123
console.log(parseInt("0xA"));//10
console.log(parseInt("070"));//70,有问题哦,请注意
console.log(parseInt("080"));//80,如属于八进制
console.log(parseInt("0xG"));//NaN,不属于十六进制
这里就有一个问题了,如上文所说,如果是以0开头的且后面跟数字字符,就会当成一个八进制来解析,但是parseInt("070")在我的最新版chrome浏览器中被解析为70而不是56,为啥呢?其实是在ECMAScript 3 JavaScript引擎中,“070”是被当成八进制字面量,但是在ECMAScript 5 JavaScript引擎中,parseInt()已经不具有解析八进制的能力了,因此,前面的零会被认为无效。
但是如果我硬要解析八进制咋整?parseInt()这个函数提供了第二个参数:转换时使用的基数(即多少进制)。例子:
console.log(parseInt("0xAF",16));//175
console.log(parseInt("AF",16));//175,因为明确知道了以十六进制进行解析,那么“0x”就不需要了
console.log(parseInt("10",2));//2
console.log(parseInt("10",8));//8
console.log(parseInt("10",10));//10
console.log(parseInt("10",16));//16
parseFloat(),与parseInt()类似,它是从第一个字符开始解析每个字符,而且也是一直解析到字符串末尾,或者遇到一个无效的浮点数字字符为止。也就是说,字符串的第一个小数点是有效的,而第二个小数点就是无效的了。除了第一个小数点有效外,parseFloat()和parseInt()的第二个区别在于它始终都会忽略前导的零,只能解析十进制。注意点:如果字符串包含的是一个可解析为整数的数,它就会返回整数。例子:
console.log(parseFloat("123木头人"));//123
console.log(parseFloat("0xA"));//0
console.log(parseFloat("22.5"));//22.5
console.log(parseFloat("22.34.5"));//22.34
console.log(parseFloat("0908.5"));//908.5
console.log(parseFloat("2.125e7"));//31250000
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 进纸 |
\ | 斜杠 |
\' | 单引号('),在用单引号表示的字符串中使用。例如:'He said,\'hey.\'' |
\" | 双引号("),在用双引号表示的字符串中使用。例如:"He said,\"hey.\"" |
\xnn | 以十六进制代码表示的一个字符(其中n为0~F)。例如,\x41表示“A” |
\unnn | 以十六进制代码nnn表示的一个Unicode字符(其中n为0~F)。例如,\u03a3表示希腊字符Σ |
4.6 String类型
String类型用于表示由零或多个16为Unicode字符组成的字符序列,即字符串。字符串可以由双引号或者单引号表示。
4.6.1 字符字面量
String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具有其他用途的字符。如下表:
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 进纸 |
\ | 斜杠 |
\' | 单引号('),在用单引号表示的字符串中使用。例如:'He said,\'hey.\'' |
\" | 双引号("),在用双引号表示的字符串中使用。例如:"He said,\"hey.\"" |
\xnn | 以十六进制代码表示的一个字符(其中n为0~F)。例如,\x41表示“A” |
\unnn | 以十六进制代码nnn表示的一个Unicode字符(其中n为0~F)。例如,\u03a3表示希腊字符Σ |
这些字符字面量可以出现在字符串中的任意位置,而且也将被看作一个字符来解析,例子:
var test ='This is the letter sigma: \u03a3.';
console.log(test.length);
这个例子中的变量text有28个字符,其中6个字符长的转义序列被作为1个字符。
当然,如果字符串中包含双字节字符,那么length属性可能不会精确地返回字符串中的字符数目。
4.6.2 字符串的特点
ECMAScript中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变摸个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。
例子:
var lang = 'Java';
lang = lang + 'Script';
实现这个操做过程如下:首先创建一个能容纳10个字符的新字符串,然后在这个字符串中填充“Java”和“Script”,最后一步是销毁元来的字符串“Java”和字符串“Script”,因为他们两个已经么有用了。这也就是很老旧的浏览器版本(例如版本低于1.0的FireFox、IE6等)拼接字符串会慢的原因。但是这些浏览器后来的版本已经解决了这个低效率的问题。
4.6.3 转换为字符串
把一个值转换成字符串有两种方式:
- 方法一,toString(),数字、布尔值、对象和字符串都有toString()方法。但null和undefined值么有这个方法。
调用toString()方法时,可以传递一个参数,即输出数值的基数。默认以十进制格式返回数值的字符串表示。它可以输出二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值。例子:
var num = 10;
console.log(num.toString());//"10"
console.log(num.toString(2));//"1010"
console.log(num.toString(8));//"12"
console.log(num.toString(10));//"10"
console.log(num.toString(16));//"a"
- 方法二,String(),转型函数,如同Number(),能够将任何类型的数值转成字符串,转换规则:
- 如果值有toString()方法,则调用该方法,并返回相应的结果;
- 如果值是null,则返回“null”;
- 如果值是undefined,则返回“undefined”。
4.7 Object类型
ECMAScript中的对象其实就是一组数据和功能的集合。Object类型是所有它的实例的基础。换句话说,Object类型所具有的任何属性和方法也同样存在与更具体的对象中。
Object的每个实例都具有下列属性和方法。
- constructor:保存着用于创建当前对象的函数。构造函数(constructor)就是Object()。
- hasOwnProperty(propertyName):用于检查给定的属性再当前对象实例中(而不是再实例的原型中)是否存在。
- isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型。(后面会讨论到原型)
- propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
- toString():返回对象的字符串表示。
- valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同。
5 操作符
ECMA-262描述了一组用户操做数据只的操作符,包括算术操作符、位操作符、关系操作符和相等操作符。他们能够适用于很多值,例如字符串、数字值、布尔值,甚至于对象。不过,再应用于对象时,相应的操作符通常都会调用对象的valueOf()和(或)toString()方法,以便取得可以操做的值。
5.1 一元操作符
只能操做一个值的操作符叫做一元操作符
1 递增和递减操作符
递增和递减借鉴与C,而且各有两个版本:前置型和后置型。
前置型:
var age= 28;
++age;
age = age + 1;
--age;
age = age - 1;
var age = 28;
var anotherAge = --age + 2;
console.log(age);//27
console.log(anotherAge);//29
后置型:
var age = 28;
age++;
age--;
var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2;//22
var num4 = num1 + num2;//21
上面的例子,应该明白了前置和后置的区别。
所有这4个操作符对任何值都适用,也就是说它们不仅仅适用于整数,还可以用于字符串、布尔值、浮点数值和对象。在应用于不同的值时,递增和递减操作符遵循下列规则。
- 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操作。字符串变量变成数值变量。
- 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为NaN。字符串变量变成数值变量。
- 在应用于布尔值false时,先将其转换为0再执行加减1的操作。布尔值变量变成数值变量。
- 在应用于布尔值true时,先将其转换为1再执行加减1的操作。布尔值变量变成数值变量。
- 在应用于浮点数值时,执行加减1的操作。
- 在应用于对象时,先调用对象的valueOf()方法以取得一个可供操作的值,然后对该值进行前述规则。如果是时NaN,则再调用toString()方法后再应用前述规则。对象变量变成数值变量。
例子:
var s1 = "2";
var s2 = "A";
var b1 = false;
var b2 = true;
var f = 1.1;
var o = {
valueOf: function () {
return -2;
}
};
console.log(++s1);//3
console.log(++s2);//NaN
console.log(++b1);//1
console.log(++b2);//0
console.log(--f);//0.10000000000000009(由于浮点舍入错误所致)
console.log(--o);//-2
var s3 = "2";
var s4 = "A";
var b3 = false;
var b4 = true;
var f1 = 1.1;
var o1 = {
valueOf: function () {
return -2;
}
};
console.log(s3++);//2
console.log(s4++);//NaN
console.log(b3++);//0
console.log(b4++);//1
console.log(f1--);//1.1
console.log(o1--);//-1
2 一元加和减操作符
简单说,一元加操作符(+)放在数值前面,对数值不会产生任何影响。一元减操作符主要用于表示负数。
例子:
var s1 = "1";
var s2 = "1.1";
var s3 = "a";
var b = false;
var f = 1.1;
var o = {
valueOf: function () {
return -1;
}
};
console.log(+s1);//1
console.log(+s2);//1.1
console.log(+s3);//NaN
console.log(+b);//0
console.log(+f);//1.1
console.log(+o);//-1
console.log(-s1);//-1
console.log(-s2);//1.1
console.log(-s3);//NaN
console.log(-b);//-0
console.log(-f);//-1.1
console.log(-o);//1