1

1 语法

1.1 区分大小写

ECMAScript中的一切(变量、函数名和操作符)都区分大小写。

1.2 严格模式

ECMAScript 5 引入了严格模式(strict mode)的概念。严格模式是为JavaScript定义了一种不同的解析与执行模型。
在严格模式下,ECMAScript 3 中的一些不确定的行为将得到处理,而且对某些不安全的操作也会抛出错误。
要在整个脚本中启用严格模式,可以再顶部添加如下代码:

"use strict" 

指定函数在严格模式下执行:

function  doSomething(){
    "use strict";
    //函数体
}

2 关键字和保留字

关键字
break、do、instanceof、typeof、case、else、new、var、catch、finally、return、void、continue、for、switch、while、debugger、function、this、with、default、if、throw、delete、in、try

保留字
ECMA-262 第五版非严格模式:class、enum、extends、super、const、export、import

ECMA-262 第五版严格模式增加以下限制:implements、package、public、interface、private、static、let、protected、yield

3 变量

ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说,每个变量仅仅是一个用于保存值得占位符而已。

var message;

像这样未经过初始化的变量,会保存一个特殊的值——undefined

给未经声明的变量赋值在严格模式下会导致抛出PeferenceError错误

4 数据类型

ES 5
5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number、String
1种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的。

ES 6 新增一种数据类型——符号对象(Symbol)

4.1 typeof 操作符

typeof 用来检测给定变量的数据类型

"undefined"——如果这个值未定义
"boolean"——如果这个值是布尔值
"string"——如果这个值是字符串
"number"——如果这个值是数值
"object"——如果这个值是对象null
"function"——如果这个值是函数

  • 调用typeof null会返回"object",因为特殊值null被认为是一个空的对象引用

4.2 Undefined 类型

Undefined类型只有一个值,即特殊的undefined。在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined

var message;
console.log(message == undefined); //true

字面量undefined的主要目的是用于比较,为了正式区分空对象指针与未经初始化的变量

4.3 Null 类型

Null类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空对象指针,而这也正式使用typeof操作符检测null值时会返回"object"的原因

var car = null;
console.log(typeof null); //object

如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null而不是其他值。这样一来,只要直接检查null值就可以知道相应的变量是否已经保存了一个对象的引用。

实际上,undefined值是派生自null值得,因此ECMA-262规定对他们的相等性测试要返回true

console.log(null == undefined); //true

4.4 Boolean 类型

Boolean类型只有两个字面值:truefalse

Boolean类型的字面值true和false是区分大小写

可以对任何数据类型的值调用Boolean()函数,而且总会返回一个Boolean值

数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 "" (空字符串)
Number 任何非零数字值 0和NaN
Object 任何对象 null
Undefined N/A undefined

n/a (N/A),是not applicable的缩写,意思是"不适用"。

4.5 Number类型

Number类型使用IEEE754格式来表示整数和浮点数值(双精度值)。为支持各种数值类型ECMA-262定义了不同的数值字面量格式。

  • 十进制

var intNum == 55;
  • 八进制
    八进制字面值的第一位必须是零(0),然后是数字序列(0~7)。如果字面值中的数值超出了范围,那么_前导零_ 将被忽略,后面的数值将被当做十进制十进制数值解析

var octalNum1 = 070; //八进制的56
var octalNum2 = 079; //无效的八进制数值——解析为79
var octalNum3 = 08;  //无效的八进制数值——解析为8

八进制字面量在严格模式下是无效的,会导致支持该模式的JavaScript引擎抛出错误。

  • 十六进制
    十六进制字面值的前两位必须是0x,后跟任何十六进制数字(0~9 及 A~F)。字母A~F可以大写,也可以小写

var hexNum1 = 0xA;    //十六进制的10
var hexNum2 = 0x1f;    //十六进制的31

在进行算数计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值

4.5.1 浮点数值

保存浮点数值需要的内存空间是保存整数值得两倍,如果小数点后面没有跟任何数字,或者浮点数值本身表示的就是一个整数(如1.0),那么该值将会被转换成整数

var floatNum1 = 1;        //小数点后面没有数字——解析为1
var floatNum2 = 10.0;    //整数——解析为10

对于那些极大或极小的数值,可以用e表示法(即科学计数法)表示浮点数值。用e表示法表示的数值等于e前面的数值乘以10的指数次幂。

var floatNum1 = 3.125e7;    //等于31250000
var floatNum2 = 3e-7;        //等于0.0000003

浮点数值得最高精度是17位小数,但在进行算术计算时其精度远远不如整数。例如,0.1加0.2的结果是0.30000000000000004

4.5.2 数值范围

由于内存的限制,ECMAScript并不能保存世界上所有的数值。

最小数值 Number.MIN_VALUE //5e-324
最大数值 Number.MAX_VALUE //1.7976931348623157e+308

如果某次计算的结果得到了一个超出JavaScript数值范围的值,那么这个值将被自动转换成特殊的Infinity值

正无穷大 Infinity
负无穷大 -Infunity
isFinite()函数可以判断一个数值是否又穷的

4.5.3 NaN

NaN,即非数值(Not a Number),是一个特殊的数值,这个数值用于本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)

任何涉及NaN的操作(例如NaN/10)都会返回NaN
NaN与任何值都不相等,包括NaN本身

console.log(NaN == NaN);    //false

ECMAScript定义了isNaN()函数,这个函数接受一个参数,该参数可以是任何类型,而函数会帮我们确定这个函数是否"不是数值"

isNaN()也适用于对象,基于对象调用isNaN()函数时,会先调用对象的valueOf()方法,再确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用toString()方法,在测试返回值

4.5.4 数值转换

Number()parseInt()parseFloat()

4.6 String类型

4.6.1 字符字面量

String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具有其他用途的字符。

  • n:换行

  • t:制表

  • b:退格

  • r:回车

  • f:进纸

  • x_nn_:以十六进制代码_nn_表示的一个字符(其中_n_为0~F)。例如,x41表示"A"

  • u_nnnn_:以十六进制代码_nnnn_表示的一个Unicode字符(其中_n_为0~F)。例如,u03a3表示希腊字符Σ

任何字符串的长度都可以通过访问其length属性取得:

var text = "This is the letter sigma: \u03a3.";
console.log(text.length);    //输出28

这个属性返回的字符数包括16位字符的数目。如果字符串中包含双字节字符,那么length属性可能不会精确地返回字符串中的字符数目。

4.6.2 字符串的特点

ECMAScript中的字符串是不可变的。字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销原来的字符串,然后再用另一个包含新值的字符串填充该变量

4.6.3 转换为字符串

要把一个值转换为一个字符串有两种方法:

  • 几乎每个值都有的toString()方法

nullundefined没有这个方法
toString()方法接受一个参数:输出数值的基数,toString()可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值(默认基数为10)

  • String()函数能够将任何类型的值转换为字符串

如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果;
如果值是null,则返回"null";
如果值是undefined,则返回"undefined"。

4.7 Object 类型

ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。

var o = new Object();    //无传参时可以省略括号,但不推荐这么做

Object的每个实例都具有下列属性和方法:

  • constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数(constructor)就是Object()

  • hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,作为参数的属性名(_propertyName_)必须以字符串形式指定(例如:o.hasOwnProperty("name"))

  • isPrototypeOf(Object):用于检查传入的对象是否是当前对象的原型

  • propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。与hasOwnProperty()方法一样,作为参数的属性名必须以字符串形式指定

  • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应

  • toString():返回对象的字符串表示

  • valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同

由于在ECMAScript中Object是所有对象的基础,因此所有对象都具有这些基本的属性和方法。

5 操作符

5.1 一元操作符

只能操作一个值的操作符叫做一元操作符

5.1.1 递增和递减操作符

  • 执行前置递增和递减操作符时,变量的值都是在语句被求值以前改变的(在计算机领域,这种情况通常被称作副效应)

var age = 29;
var antherAge = --age + 2;

console.log(age);            //输出28
console.log(anotherAge);    //输出30
  • 执行后置递增和递减操作符时,变量的值都是在语句被求值之后改变的

var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2;    //等于22
var num4 = num1 + num2;        //等于21

递增递减操作符对任何值都适用

5.1.2 一元加和减操作符

在对非数值应用一元加(减)操作符时,该操作符会像Number()函数一样对这个值执行转换。

5.2 位操作符

......

5.3 布尔操作符

5.3.1 逻辑非

逻辑非操作符由一个叹号(!)表示,可以应用于ECMAScript中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。
同时使用两个逻辑非操作符,实际上就会模拟Boolean()转型函数的行为

5.3.2 逻辑与

逻辑与操作符由两个和号(&&)表示,有两个操作数
逻辑与操作可以应用于任何类型的操作数,而不仅仅是布尔值。在有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值:

  • 如果第一个操作数是对象,则返回第二个操作数

  • 如果第二个操作数是对象,则只有在第一个操作数的求值结果为true的情况下才会返回该对象

  • 如果两个操作数都是对象,则返回第二个操作数

  • 如果第一个操作数是null,则返回null

  • 如果第一个操作数是NaN,则返回NaN

  • 如果第一个操作数是undefined,则返回undefined

逻辑与操作属于短路操作,如果第一个操作数能够解决结果,那么久不会再对第二个操作数求值

var found = true;
var result = (found && someUndefinedVariable);    //这里会发生错误
console.log(result);    //这一行不会执行

上面代码中,当执行逻辑与操作符时会发生错误,因为变量someUndefinedVariable没有声明

var found = false;
var result = (found && someUndefinedVariable);    //不会发生错误
console.log(result);    //会执行("false")

5.3.3 逻辑或

逻辑或操作符由两个竖线符号(||)表示,有两个操作数
与逻辑与相似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值:

  • 如果第一个操作数是对象,则返回第一个操作数

  • 如果第一个操作数的求值结果为false,则返回第二个操作数

  • 如果两个操作数都是对象,则返回第一个操作数

  • 如果两个操作数都是对象,则返回第一个操作数

  • 如果两个操作数都是null,则返回null

  • 如果两个操作数都是undefined,则返回undefined

逻辑或操作符也是短路操作符。也就是说,如果第一个操作数的求值结果为true,就不会对第二个操作数求值了

5.6 关系操作符

小于(<)、大于(>)、小于等于(<=)、大于等于(>=)
当关系操作符的操作数使用了非数值时,会进行数据转换或完成某些奇怪的操作:

  • 如果两个操作数都是数值,则执行数值比较

  • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值

  • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较

  • 如果一个操作数是对象,则调用这个对象的valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有valueOf()方法,则调用toString()方法,并用得到的结果根据前面的规则执行比较

  • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较

任何操作数与NaN比较,都会返回false

5.7 相等操作符

5.7.1相等和不相等

如果两个操作数数据类型不同,则会先转换数据类型(通常称为强制转型)再比较

  • nullundefined是相等的

  • 要比较相等性之前,不能将nullundefined转换成其他任何值

  • 有一个操作符为NaN时,相等操作符返回falseNaN不等于NaN

  • 如果两个操作数都是对象,则比较它们是不是同一个对象

5.7.2 全等和不全等

除了在比较之前不转换操作数之外,全等和不全等操作符没有什么区别

5.8 条件操作符

variable = boolean_expression ? true_value : false_value;

var max = (num1 > num2) ? num1 : num2;

5.9 赋值操作符

等于号(=)

5.10 逗号操作符

逗号(,)

6语句

6.1 if语句

if(1 > 25){
    console.log();
}else{
    console.log();
}

6.2 do-while语句

var i = 0;
do{
    i += 2;
}while(i < 10);
console.log(i);

6.3 while语句

var i = 0;
while(1 < 10){
    i += 2;
}

6.4 for语句

var count = 10;
for(var i = 0; i < count; i++){
    console.log(i);
}

由于ECMAScript中不存在块级作用域,因此在循环内部定义的变量也可以在外部访问到

for语句中的初始化表达式、控制表达式和循环后表达式都是可选的。将这三个表达式全部省略,就会创建一个无限循环

6.5 for-in语句

for-in语句是一种精准的迭代语句,可以用来枚举对象的属性

for(var propName in window){
    document.write(propName);
}

ECMAScript对象的属性没有顺序。因此,通过for-in循环输出的属性名的顺序是不可预测的

6.6 label语句

使用label语句可以在代码中添加标签,以便将来使用

start: for(var i = 0; i < count; i++){
    console.log(i);
}

这个例子中定义的start标签可以在将来有breakcontinue语句引用。加标签的语句一般都要与for语句等循环语句配合使用

6.7 break和continue语句

breakcontinue语句用于在循环中精确地控制代码的执行

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;
        }
        num++;
    }
}
console.log(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++;
    }
}
console.log(num);    //95
                    //如果两个循环都自然结束,num的值应该是100

6.8 with语句(舍弃!)

严格模式下不允许使用with语句,否则将视为语法错误。
由于大量使用with语句会导致性能下降,同时也会给调试代码造成困难,因此不建议使用with语句

6.9 switch语句

var num = 25;
switch (true){
    case num < 0:
        console.log("0");
        break;
    case num >= 0 && num <= 10:
        console.log("0");
        break;
    default:
        console.log("0");
}

switch语句在比较值时使用的是全等操作符,因此不会发生类型转换

7 函数

函数中的return语句可以不带有任何返回值。在这种情况下,函数在停止执行后将返回undefined值。

推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值。否则,如果函数有时候返回值,有时候不返回值,会给调试代码带来不便

7.1 理解参数

ECMAScript中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。

在函数体内可以通过arguments对象来访问这个参数数组

ECMAScript函数有一个重要的特点:命名的参数只提供便利,但不是必须的。

命名参数可以与arguments对象一起使用,arguments的值永远与对应命名参数的值保持同步。

没有传递值的命名参数将自动被赋予undefined值。

严格模式下不允许重写命名参数或者arguments的值,虽然可以执行,但是命名参数与arguments对应的值将不再同步

7.2 没有重载

ECMAScript函数不能像传统意义上那样实现重载。ECMAScript函数没有签名,因为其参数是由包含零或多个值的数组来表示的。而没有函数签名,真正的重载是不可能做到的。

如果定义了两个名字相同的函数,则该名字只属于后定义的函数,先定义的函数将被覆盖


Cor
63 声望9 粉丝