JavaScript学习笔记&知识总结(二)基本概念(语法、数据类型、函数)

知识总结(二)


任何语言的核心都必然会描述这门语言最基本的工作原理。而描述的内容通常都要涉及这门语言的语法、操作符、数据类型、内置功能等用于构建复杂解决方案的基本概念。

1. 语法

ECMAScript的语法大量借鉴了C和其他类C语言的语法。因此熟悉这些语言的开发人员在接受ECMAScript更加宽松的语法时,一定会有一种轻松自在的感觉。

1.1 区分大小写

ECMAScript中的一切都区分大小写。这也就意味着,变量名test和变量名Test分别表示两个不同的变量,而函数名不能使用typeof,因为它是一个关键字,但typeOf则完全可以是一个有效的函数名。

1.2 标识符

所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。标识符是按照下列格式规则组合起来的一或多个字符:
第一个字符必须是一个字母、下划线或者一个美元符号。
其他字符可以是字母、下划线、美元符号或数字。

按照惯例ECMAScript标识符采用驼峰大小写格式,也就是第一个字母小写,剩下的每个单词的首字母大写,例如:
firstSecond
myCar
doSomethingImportant
没有人硬性要求采用这种格式,但为了与ECMAScript内置的函数和对象命名格式统一,可以将其当作一种最佳实践。

注意:不能把关键字、保留字、true、false和null作为标识符。

1.3 注释

ECMAScript采用C风格的注释,包括单行注释和块级注释。单行注释以两个斜杠//开头,如下所示:

// 单行注释

块级注释以一个斜杠/和一个星号*开头,以一个星号和一个斜杠结尾,如下所示:

/*块级
  注释*/

1.4 严格模式

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

"use strict";

这行代码看起来像是字符串,也没有赋值给任何变量,其实他是一个编译指示,用于告诉支持的JavaScript引擎切换到严格模式。这是为不破坏ECMAScript3语法而特意选定的语法。

1.5 语句

ECMAScript中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾,如下图所示:

var sum = a + b//有效但不推荐
var diff = a - b;//有效的语句-推荐

虽然语句结尾的分号不是必须的,但建议任何时候都不要省略它。因为加上这个分号可以避免很多错误,开发人员也可以放心通过删除多余的空格来压缩代码。另外,加上分号以后解析器就不必再花时间推测应该在哪里插入分号,这样会在某些情况下提升代码性能。
可以使用C风格的语法把多条语句组合到一个代码块中,即代码块以左花括号开头,以右花括号结尾:

if (test) {
    test = false;
    alert(test);
}

虽然条件控制语句只在执行多条语句的情况下才要求使用代码块,但最佳实践是始终在控制语句中使用代码块,即使代码块中只有一条语句。
在控制语句中使用代码块可以让编码意图更加清晰,而且也能降低修改代码时出错的几率。

2. 关键字和保留字

ECMA-262描述了一组具有特定用途的关键字,这些关键字可用于表示控制语句的开始或结束,或用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。以下是ECMAScript的全部关键字(带*上标的是第5版新增的关键字):
在这里插入图片描述
ECMA-262还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特定用途,但他们有可能在将来被用作关键字。以下是ECMA-262第3版定义的全部保留字:
在这里插入图片描述
let和yield是第5版新增的保留字,其他保留字都是第3版定义的。
在实现ECMAScript3的JavaScript引擎中使用关键字做标识符,会导致“Identifier Expected”错误,而使用保留字可能会也可能不会导致相同的错误,取决于特定的引擎。
一般来说,最好都不要使用关键字和保留字作为标识符和属性名,以便与将来的ECMAScript版本兼容。

3. 变量

ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说,每个变量仅仅是一个用于保存值的占位符而已。
定义变量时要使用var操作符(var是一个关键字,后跟变量名),如下:

var message;

这行代码定义了一个名为message的变量,该变量可以用来保存任何类型值(像这样未经初始化的变量,会保存undefined)ECMAScript也支持直接初始化变量,因此在定义变量的同时就可以设置变量的值,如下:

var message = 'hi';

像这样初始化变量并不会把他标记为字符串类型;初始化的过程就是给变量赋一个值这么简单。因此,可以在修改变量值的同时修改变量的类型,但不建议修改变量所保存值的类型,但这种操作在ECMAScript中有效。
有一点必须明确,用var操作符定义的变量将成为定义该变量的作用域中的局部变量。也就是说,如果在函数中使用var定义一个变量,那么这个变量在函数退出后就会被销毁
例如:

function test() {
    var message =  'hi!';
}
test();
alert(message);//错误!

当函数被调用时,就会创建该变量并为其赋值。在此之后,这个变量又会被销毁,因此下一行代码就会导致错误。
可以省略var操作符,从而创建一个全局变量,但不推荐这样做,全局变量很难维护。
可以使用一条语句定义多个变量,只要像下面这样把每个变量(初始化不初始化都可)用逗号分隔开:

var message = 'hi',
    found,
    age = 29;

这个例子定义了三个变量,由于变量类型是松散类型的,因而使用不同类型初始化变量的操作可以放在一条语句中完成。虽然代码里的缩进和换行不是必须的,但这样做可以提高可读性。

4. 数据类型

ECMAScript中有5种简单数据类型(也称为基本数据类型):Undefined,Null,Boolean,String,Number。还有1种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的。ECMAScript不支持创建任何自定义类型的机制,所有值都是以上6种数据类型之一。
因为ECMAScript数据类型具有动态性,因此没有定义其他数据类型的必要了。(可以理解为,C中的struct,enum类型在JavaScript中都可以用Object实现)

4.1 typeof操作符

鉴于ECMAScript是松散类型的,所以需要有一种手段来检测给定变量的数据类型——typeof就是负责提供这方面信息的操作符。对一个值使用typeof操作符可能返回下列某个字符串:
"undefined"——如果这个值未定义
“boolean”——如果这个值是布尔值
“string”——如果这个值是字符串
“number”——如果这个值是数值
“object”——如果这个值是对象
“function”——如果这个值是函数

要注意的是typeof是一个操作符,而不是一个函数,因此后面不用跟括号。

注意:
1.从技术角度讲,函数在ECMAScript中是对象,不是一种数据类型。然而,函数也有一些特殊的属性,因此用typeof操作符来区分函数和对象是有必要的
2.typeof null的值是object,因为特殊值null被认为是一个空的对象引用。

4.2 Undefined

undefined类型只有一个值,既特殊的undefined。使用var声明变量但未对其初始化时,这个变量的值就是undefined。
需要注意的是,对未初始化的变量执行typeof操作符会返回undefined值,而对尚未声明的变量执行typeof,也会返回undefined值。所以,即便未被初始化的值会被自动赋予undefined,但显式的初始化变量依然是明智的选择。如果能做到这一点,那么当typeof返回undefined时,我们就知道这个变量是未声明,而不是未初始化。

4.3 Null类型

Null类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null表示一个空对象指针,而这也是typeof null返回object的原因。
如果定义的变量将来准备用于保存对象,那么最好将该变量初始化为null而不是其他值。这样依赖,只要检查null值就能知道相应的变量是否已经保存了一个对象的引用,如下例:

if (car != null){
    //执行操作
}

实际上,undefined值是派生自null值的。所以用相等(非全等,后续详细介绍)操作符比较他俩,会返回true。
尽管null和undefined有这样的关系,但他们的用途完全不同。
只要意在保存对象的变量还没有真正的保存对象,就应该明确的让变量保存null值。这样做不仅可以体现null作为空对象指针的惯例,也有助于进一步区分null(已声明)和undefined(未声明)。

4.4 Boolean类型

Boolean类型是ECMAScript中使用的最多的一种类型,该类型只有两个字面值:true和false。这两个值与数字值不是一回事,因此true不一定等于1,false也不一定等于0。以下是为变量赋Boolean类型值的例子:

var found = true;
var lost = false;

需要注意,true和false是区分大小写的,其他混合大小写形式不是Boolean值,而是标识符。
虽然Boolean类型的字面值只有两个,但是ECMAScript中所有类型的值都有与这两个Boolean值等价的值。要将一个值转换为与其等价的Boolean值,可以使用转型函数Boolean(),如下例所示

var message = "Hello World!";
var messageBoolean = Boolean(message);

可以对任何数据类型的值调用Boolean()转型函数,至于返回的值是true还是false,取决于要转换值得数据类型及其实际值。下表给出了各种数据类型以及对应的转换规则。
在这里插入图片描述
这些转换规则对理解流控制语句(如if语句)自动执行相应的Boolean转换非常重要。

var message = 'hi!';
if (message){
    alert('value is true');
}
//这里的if(message) 等于 if(Boolean(message))

由于存在这种自动执行的Boolean转换,因此确切的知道在流控制语句中使用的是什么变量至关重要。

4.5 Number类型

Number类型采用IEEE754格式来表示整数和浮点数值(浮点数值在某些语言中也被称为双精度数值)。
最基本的数值字面量格式是十进制整数,十进制整数可以直接在代码中输入。除了十进制以外,整数还可以通过八进制或者十六进制的字面值来表示。八进制和十六进制在此不多叙述,有兴趣的朋友可以自行学习。
在进行算术计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值。
(1)浮点数值
所谓浮点数值,就是该数值中必须包含一个小数点,而且小数点后必须至少有一位数字。
由于保存浮点数值需要的内存空间是保存整数值的两倍,因此ECMAScript会不失时机的将浮点数值转换为整数值。
对于哪些极大或极小的数值,可以用e表示法表示的浮点数值表示,用e表示的数值等于e前面的数值乘以10的指数次幂。3.125e7 = 31250000。
注意:浮点数值在进行算术计算时的精确度,远远不如整数,例如0.1加0.2不是0.3,而是0.3000000000000004,这个误差导致无法测试特定的浮点数值,因此 永远不要测试某个特定的浮点数值!
(2)数值范围:
ECMAScript因为内存限制,不能保存世界上所有的数值,ECMAScript能够保存的最小数值存在Number.MIN_VALUE中。
如果某次计算结果得到了一个超出JavaScript数值范围的值,那么这个数值将会被自动转换成特殊的Infinity值,如果这个数值是负数,被转换成-Infinity。
如果某次计算返回了正或负的Infinity值,那么该值无法继续参与下一次的计算,因为它不是能够参与计算的数值。
想确定一个数值是否有穷,可以用isFinite()函数,这个函数在参数位于最小与最大数值之间时会返回true。
(3)NaN
NaN即非数值是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况。比如任何数值除以非数值,会返回NaN,而在其他语言中会导致错误从而停止代码执行。
NaN本身有两个非同寻常的特点。首先,任何涉及NaN的操作(NaN/10)都会返回NaN,这个特点在多步计算中有可能导致问题。另外,NaN与任何值都不相等,包括NaN本身。
针对NaN的这个特点,ECMAScript定义了 isNaN()函数。这个函数接受一个参数,该参数可以是任何类型,而该函数会帮我们确定这个参数是否”不是数值“。在接受到一个参数以后,它会尝试将这个值转换为数值。某些不是数值的值会直接转换为数值,而任何不能转换为数值的值会导致这个函数返回true。
isNaN也适用于对象,基于对象调用时,会首先调用对象的ValueOf方法,然后确定该方法返回的值能否转换为数值,不能则基于这个返回值调用toString方法,再测试返回值。这个过程也是ECMAScript中内置函数和操作符的一般流程。
(4)数值转换(与一元加操作符步骤相同)
有3个函数可以把非数值转换为数值Number()、parseInt()和parseFloat()。第一个函数,Number()可以用于任何数据类型,而另两个函数则专门用于把字符串转换为数值。
Number()函数的转换规则如下:
如果是Boolean值,true和false将分别被转换为1和0;
如果是数字值,只是简单的传入和返回;
如果是null值,返回0;
如果是undefined,返回NaN;
如果是字符串有以下规则:
如果字符串中只包含数字,则转换为十进制数值,最前的0会被忽略
如果字符串中包含有效浮点格式,则转换为对应浮点数值
如果字符串中包含有效十六进制格式,将其转换为相同大小十进制整数
字符串为空,转换为0
字符串中包含除上述之外字符,转换为NaN
如果是对象,会首先调用对象的ValueOf方法,然后确定该方法返回的值能否转换为数值,不能则基于这个返回值调用toString方法,再按前面的规则转换返回的字符串值。

由于用Number函数比较复杂且不够合理,一般处理整数时更常用的是parseInt,它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符或符号,就返回NaN。也就意味着,用parseInt转换空字符串会返回NaN而不是0。如果第一个字符是数字字符,会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。
可以为parseInt提供第二个参数,转换时用的基数(即多少进制)。如果知道要解析的值是十六进制,那么指定基数16可以保证得到正确结果。
多数情况下,我们要解析的都是10进制的数值,因此始终将10作为第二个参数是非常有必要的。

4.6 String类型

String类型用于表示由零或多个16位Unicode字符组成的字符序列,即字符串。字符串可以由双引号或单引号表示:

var message1 =  'hi';
var message2 = "hi";

(1)字符字面量:
String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具有其他用途的字符。
在这里插入图片描述
这些字符字面量可以出现在字符串中的任意位置,而且也将被作为 一个 字符来解析。
任何字符串的长度都可以通过访问其length属性取得,例如:

var count = text.length;

这个属性返回的字符数包括16位字符的数目。如果字符串中包含双字节字符,那么字符串可能不会精确的返回字符串中的字符数目。
(2)字符串的特点
ECMAScript中的字符串是不可变的,也就是说,字符串一旦创建,他们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充变量。

var lang = 'Java';
lang = lang + 'Script';

以上示例中的变量lang开始时包含字符串Java,而第二行代码把lang的值重新定义为Java与Script的组合,即JavaScript。实现这个操作的过程如下:首先创建一个能容纳10个字符的新字符串,然后再在这个字符串中填充Java和Script,最后一步是销毁原来的字符串Java和字符串Script,这个过程是在后台发生的。
(3)转换为字符串
要把一个值转换为一个字符串有两种方法,一种是toString()方法。
这个方法唯一要做的就是返回相应值的字符串表现。
数值、布尔值、对象和字符串值都有toString方法,但null和undefined没有这个方法。
在调用数值的toString方法时,可以传递一个参数;输出数值的基数。默认情况下,toString返回十进制格式的数值,参数可以输出其他进制表示数值的字符串值。
在不知道要转换的值是不是null或者undefined时,可以使用转型函数String(),这个函数能将任何类型的值转换为字符串,遵循以下方法
如果值有toString方法,则调用该方法
如果值是null,则返回“null”
如果值是undefined,则返回“undefined”
要把某个值转换为字符串,可以使用加号操作符把它与另一个字符串加在一起(后续详细叙述)。

4.7 Object类型

ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。而创建Object类型的实例并为其添加属性或方法就可以创建自定义对象。

var o = new Object();

Object的每个实例都具有以下属性和方法。
1.constructor:保存着用于创建当前对象的函数。
2.hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例(非原型)中是否存在。例如:o.hasOwnProperty(“Name”)
3.propertyIsEnumerable(propertyName):用于检查给定的属性能否使用for-in语句来枚举。
4.LocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
5.toString():返回对象的字符串表示
6.valueOf():返回对象的字符串、数值或布尔值表示,通常与同String()方法的返回值相同。

5. 操作符

ECMA描述了一组用于操作数据的操作符,包括算术操作符、位操作符、关系操作符和相等操作符。ECMAScript操作符的与众不同之处在于他们适用于很多值,例如字符串、数字值、布尔值,甚至对象。
注:本文不讲解位操作符,有兴趣的朋友请自行了解。

5.1 一元操作符

只能操作一个值的操作符叫做一元操作符。一元操作符是ECMAScript中最简单的操作符。
1.递增和递减操作符
递增和递减操作符直接借鉴自C语言,而且有两个版本,前置型和后置型。前置型应该位于要操作的变量之前,而后置型操作符则应该位于要操作的变量之后。

var age = 29;
age++;
age--;
++age;
--age;

执行前置递增和递减操作时,变量的值都是在语句被求值前改变的。后置递增和递减操作时在包含他们的语句被求值之后才执行的。
2.一元加和减操作符
这两个ECMAScript操作符的作用与数学书上讲的一模一样。一元加以一个加号表示,放在数值前面,对数值不会产生任何影响。
不过,在对非数值应用一元加操作符时,该操作符会像Number一样对值执行转换再操作。
一元减操作符主要用于表示负数,例如将1转换成-1。在将一元减操作符应用于数值时,该值会变成负数。而当应用于数值时,遵循和一元加一样的规则。最后再将得到的数值转换为负数。
一元加减操作符主要用于基本的算术运算,也可以像前面一样用于转换数据类型。

5.2 布尔操作符

在一门编程语言中,布尔操作符的重要性堪比相等操作符。如果没有测试两个值关系的能力,那么例如if…else和循环之类的语句就不会有用武之地了。布尔操作符一共有3个:非(NOT)、与(AND)和或(OR)。
1.逻辑非
逻辑非操作符由一个叹号!表示,可以应用于ECMAScript中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。逻辑非操作符首先会将它的操作数转换为一个布尔值,然后再对其求反。
所以可以得出,使用两个!就相当于对值使用了Boolean函数。
2.逻辑与
逻辑与操作符由两个和号&&表示,有两个操作数,如下面例子所示:
var result = true && false;
当两个操作数都为真时,逻辑与才为1。
在这里插入图片描述
逻辑与操作可以应用于任何类型的操作数,而不仅仅是布尔值。在有一个操作数,在有一个操作数不是布尔值的情况下,逻辑于操作就不一定放回布尔值;
逻辑与属于短路操作,如果第一个操作数能决定结果,就不会再对第二个操作数求值。对于逻辑与而言,如果第一个操作数是false,则无论第二个操作数是什么值,结果都不在可能是true了。
3.逻辑或
逻辑或操作符由两个竖线符号表示,||有两个操作数,真值表如下:
在这里插入图片描述
与逻辑与操作相似,逻辑或操作符也是短路操作符。也就是说,如果第一个操作数的求值结果为true,就不会对第二个操作数求值了。
我们可以利用这一点来避免为变量赋null或undefined值:

var a = b||c;

这个例子中,b是优先要赋给a值的变量,如果b中不包含有效值,则由c来提供后备值。ECMAScript程序的赋值语句经常会使用这种模式。

5.3 乘性操作符

乘性操作符定义了3个操作符:乘法、除法和求模。不多讲述

5.4 加性操作符

基本功能不多讲述,但如果有一个操作数是字符串时,应用如下规则:
如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来;
如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来。
例:

var result = 5 + '5';

上面代码得出的结果是"55",因为第二个操作数是字符串,第一个操作数就转换为字符串,进行两个字符串的拼接。

5.5 关系操作符

小于、大于、小于等于这几个关系操作符用于对两个值进行比较,比较的规则与我们在数学课上所学的一样,这几个操作符都返回一个布尔值。
与ECMAScript中的其他操作符一样,当关系操作符的操作数使用了非数值时,也要进行数据转换。
注意:在字符串比较时,比较的是两个字符串对应的ASCII编码,而ASCII编码区分大小写,所以在比较字符串时,最好将字符串全部转化为相同的大小写形式再进行比较。

5.6 相等操作符

1.相等和不相等
ECMAScript中的相等操作符由两个等于号==表示,如果两个操作数相等,则返回true,不相等操作符由!=表示,如果两个操作数不相等,则返回true。这两个操作符都会先转换操作数(通常称为 强制转型),然后再比较它们的相等性。
2.全等和不全等
除了比较之前不转换操作数之外,全等和不全等操作符与相等和不相等操作符没有什么区别。全等操作符由3个等于号表示,它只在两个操作数未经转换就相等的情况下返回true。
由于相等和不相等操作符存在类型转换问题,而为了保持代码中数据类型的完整性,推荐使用全等和不全等操作符

5.7 条件操作符

条件操作符应该算是ECMAScript中最灵活的一种操作符了。而且遵循与Java中条件操作符相同的语法形式,如下面的例子所示:

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

这个例子中,max保存最大的值,如果num1大于num2,将num1的值赋给max;如果num1小于num2,将num2的值赋给max。

5.8 赋值操作符

赋值操作符由等于号=表示,作用就是把右侧的值赋给左侧变量,如下面例子所示:

var num = 10;
num += 10;

其中第二行代码就是num = num + 10的简写形式。

5.9 逗号操作符

使用逗号操作符可以在一条语句中执行多个操作。可以用于声明多个变量,用于赋值时,总会返回表达式中的最后一项。

6. 函数

函数对任何语言来说都是一个核心的概念。通过函数可以封装多条语句,而且可以在任何地方任何时候调用执行。ECMAScript中的函数使用function关键字来声明,后跟一组参数以及函数体,函数基本语法如下

function functionName(arg0,arg1...argN){
}

函数可以通过其函数名来调用,后面还要加上一对圆括号和参数。ECMAScript中的函数在定义时不必指定是否返回值。实际上,任何函数在任何时候都可以通过return语句后跟要返回的值来实现返回值。
函数会在执行完return语句后停止并立即退出。

ECMAScript函数的参数跟其他大多数语言中函数的参数有所不同。ECMAScript函数不介意传递进来多少个参数,也不在乎进来参数是什么数据类型。也就是说,即使你定义的函数只接受两个参数,调用时也不一定要穿两个,可以传一个、三个甚至不传。之所以会这样,是因为ECMAScript中的参数在内部使用一个数组来表示,函数接收的始终是这个数组,而不关心数组中包含哪些参数。如果这个数组中不包含任何元素,无所谓,包含多个元素也没问题。在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数.
JavaScript中的函数没有重载,因为函数名仅仅是一个指向函数对象的变量,当定义同名函数时,指针只是改变指向,指向后一个函数,而断开和先定义函数的连接。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值