js

二、JavaScript 基本语法

2017-11-06  本文已影响0人  霜天晓

1、标识符

标识符是指变量、函数、属性的名字,或函数的参数。

格式规则:

2、关键字

关键字用途:

关键字举例

break           do             instanceof       typeof  
case            else           new              var  
catch           finally        return           void  
continue        for            switch           while  
debugger*       function       this             with  
default         if             throw            let
delete          in             try              yield

3、变量

  ECMAScript 的变量时松散类型的,所谓松散类型就是可以用来保存任何类型的数据。
  初始化变量:给变量赋值。

可以在修改量值的同时修改值的类型,但不推荐。

4、数据类型

5 种简单数据类型(基本数据类型):

1 种复杂数据类型 —— Object:本质上是由一组无序的名值对组成的。

4.1、typeof 操作符

  因为 ECMAScript 是松散类型的,所以需要一种手段来检测给定变量的数据类型 —— typeof就是用来检测变量数据类型的操作符。

typeof 操作符的返回值:

用法:

var message = " some string";
typeof message;    // "string"
typeof(message);   // "string"

注意:typeof 是操作符而不是函数,因此圆括号可以使用,但不是必需。

4.2、undefined 类型

  undefined 类型只有一个值,即 undefined。使用 var 声明变量但未初始化时,这个变量的值就是 undefined。
  包含 undefined 值的变量与尚未定义的变量是不一样的。例:

var message;  // 变量声明后默认取得了 undefined 值
// 下面这个变量并没有声明
// var age

console.log(message);   // "undefined"
console.log(age);      // 产生错误:Uncaught ReferenceError: age is not defined  

  对未初始化的变量执行 typeof 操作符会返回 undefined 值,对未声明的变量执行 typeof 操作符同样会返回 undefined 值。例子:

var message;  // 变量声明后默认取得了 undefined 值
// 下面这个变量并没有声明
// var age

console.log(typeof message);   // "undefined"
console.log(typeof age);       // "undefined"

建议:显示地初始化变量。如果这样做,那么当 typeof 操作符返回 "undefined" 值时,就能知道被监测的变量还没有被声明,而不是尚未初始化。

4.3 Null 类型

  Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null 。 从逻辑角度看, null 值表示一个空对象指针。例:

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

建议:如果定义的变量准备用于保存对象,最好将该变量初始化为 null 。这样只要直接检查 null 的值就可以知道相应的变量是否已经保存了一个对象的引用。例:
if (a != null) {// 对 a 对象执行某些操作}

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

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

  尽管 null 和 undefined 有这样的关系,但它们的用途完全不同。无论在什么情况下都没有必要吧一个变量的值显示地设置为 undefined,可是同样的规则对 null 不适用。只要意在保存对象的变量还没有真正的保存对象,就应该明确的让该变量保存 null 值。这样不仅可以体现 null 作为空对象指针的惯例,而且也有助于进一步区分 null 和 undefined。

4.4 Boolean 类型

  Boolean 类型是 ECMAScript 中使用最多的一种类型,该类型只有两个字面值: true 和 false。

注意:Boolean 类型的字面值 true 和 false 是区分大小写的。也就是说,True 和 False (以及其他的混合大小写形式)都不是 Boolean 值,只是标识符。

  虽然 Boolean 类型的字面值只有两个,但 ECMAScript 中所有类型的值都有与这两个 Boolean 值等价的值。可以调用转型函数 Boolean() 将一个值转换为其对应的 Boolean 值。

数据类型 转换为 true 的值 转换为 false 的值
Boolean true false
Undefined n/a undefined
String 任何非空字符串 " " (空字符串)
Number 任何非零数字值(包括无穷大) 0 和 NaN
Object 任何对象 null

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

4.5、Number 类型

数字字面量格式

var octalNum1 = 070;  // 八进制的56
var octalNum2 = 079; // 无效的八进制数值—解析为79
var octalNum3 = 08;  // 无效的八进制数值—解析为8
var hexNum1 = 0xA;  //  十六进制的 10
var hexNum2 = 0x1f;    // 十六进制的 31 

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

4.5.1、 浮点数值

浮点数值 — 该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。

小数点前面可以没有整数,但不建议这样写

4.5.2、 数值范围

ECMAScript能够表示的数值(大多数浏览器中):

确定一个数值是不是有穷的,使用 isFinite() 函数,有穷返回 true

4.5.3、NaN

  NaN, 非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误, 从而影响其他代码的执行)。

NaN 本身有两个非同寻常的特点:

  isNaN() 函数,可以判断一个值是否“不是数值”,,任何不能被转换为数值的值都会导致这个函数返回 true。

4.5.4、数值转换

将非数值转换成数值:

Number() 函数的转换规则:

var num1 = Number("Hello world!");  // NaN
var num2 = Number(" ");             // 0
var num3 = Number("000011");        // 11
var num4 = Number(true);            // 1

一元加操作符的操作与 Number() 函数相同

  由于 Number() 函数在转换字符串是比较复杂而且不够合理,因此在处理整数时更常用的是 parseInt() 函数。
  parseInt() 函数在使用时应始终指定基数。
  parseFloat() 函数只解析十进制数值。

4.6、String 类型

  String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串。字符串可以由双引号(")或单引号(')表示,这两种写法都是有效的,但前后必须一致。

4.6.1、字符字面量

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

字面量 含义
\n 换行
\t 制表
\b 空格
\r 回车
\f 进纸
\ 斜杠
' 单引号(')
" 双引号(")
4.6.2、字符串的特点

  ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后在用另一个包含新值的字符串填充该变量。这个过程是在后台发生的,而这也是在某些旧版本的浏览器(如版本低于1.0的FIrefox、IE6等)中拼接字符串时速度很慢的原因所在。但在这些浏览器后来的版本已经解决了这个低效率的问题。

4.6.3、转换为字符串

两种方法:

使用:

var num = 10;
var n = null;
var boolean  = true;
// toString()
num.toString();        // "10"
num.toString(2);       // "1010"
boolean  .toString();  // "true"
num.toString(n);       // 报错
// String 
String(num);          // "10"
String(n);            // "null"
String(boolean  );    // "true"

将某个值转换为字符串:num + " ";

4.7、Object类型

  ECMAScript 中的对象是一组数据和功能的集合。创建 Object 类型的实例并为其添加属性和(或)方法,就可以创建自定义对象。

var o = new Object();

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

5、 操作符

5.1、一元操作符

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

5.1.1、递增和递减操作符
var age = 0;

递增和递减操作符作用于其它数据类型的值时:

5.1.2、一元加和减操作符

一元加操作符以一个加号(+)表示,对数值不会产生影响

var num = 0;
num = +num;  //  仍然是 0

  对非数值应用一元加操作符时,该操作符回像 Number() 转型函数一样对这个值进行转换。
  一元减操作符用于数值时,该值变为负数,用于非数值时,同一元加操作符规则相同,再将得到的数值转为负数。

var b = false;   // 0

5.2、位操作符(待定)

位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。

5.3、布尔操作符

布尔操作符共有 3 个:

5.3.1、逻辑非

  逻辑非操作符由一个叹号(!)表示,可以应用与ECMAScript中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。逻辑非操作符会先将它的操作数转换为一个布尔值,再对其求反。

逻辑非操作符遵循规则:

同时使用两个逻辑非操作符(!!)将一个值转换为布尔值,同 Boolean() 函数相同。

5.3.2、逻辑与

逻辑与操作符由两个和号(&&)表示,有两个操作数。
逻辑与的真值表:

第一个操作数 第二个操作数 结果
true true true
true false false
false true false
false false false

  逻辑与操作可以应用于任何类型的操作数。在有一个操作数不是布尔值的情况下,逻辑与操作不一定返回布尔值,遵循规则:

  逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,就不会再对第二个操作数求值。

5.3.3、逻辑或

逻辑或操作符由两个竖线符号(||)表示,有两个操作数。

var result = true || false;

逻辑或的真值表:

第一个操作数 第二个操作数 结果
true true true
true false true
false true true
false false false

  逻辑或操作可以应用于任何类型的操作数。在有一个操作数不是布尔值的情况下,逻辑或操作不一定返回布尔值,遵循规则:

  逻辑或操作符是短路操作,即如果第一个操作数的求值结果为 true,就不会对第二个操作数求值了。
  使用逻辑或的这一行为来避免为变量赋 null 或 undefined 值。

var obj = preferredObjcet || backupObject

5.4、乘性操作符

  ECMAScript定义了 3 个乘性操作符:乘法、除法、求模。
  在操作数为非数值的情况下会执行自动的类型转换,后台会先使用 Number() 转型函数将其转换为数值,也就是说,空字符串被当作 0,布尔值 true 被当作 1。

5.4.1、乘法

乘法操作符由一个星号(*)表示,由于计算两个数值的乘积。

var reslult = 10 * 10;

在处理特殊值的情况下,乘法操作符遵循下列特殊的规则:

5.4.2、除法

除法操作符由一个斜线符号(/)表示,执行第二个操作数除第一个操作数的计算。

var a, b;
a 除以b ,a 是被除数、b是除数(a / b)
a 除 b,b是被除数、a是除数(b / a)

除法操作符遵循下列特殊的规则:

5.4.3、求模

求模(余数)操作符由一个百分号(%)表示。

var result = 26 % 5;   // 等于 1

求模操作符遵循下列特殊的规则:

5.5、加性操作符

5.5.1、加法
var result = 1 + 2;

两个操作数都是数值,执行常规的加法计算,然后根据下列规则返回结果:

一个操作符是字符串,应用下列规则:

  有一个操作数是对象、数值、布尔值,调用 toString() 方法取得相应的字符串值,在应用前面关于字符串的规则。
  对于 undefined 和 null,分别调用 String() 函数并取得字符串 “undefined" 和 "null"。

5.5.2、减法

减法遵循规则:

5.6、关系操作符

  小于(<)、大于(>)、小于等于(<=)、大于等于(>=)这几个关系操作符用于对两个值进行比较,返回一个布尔值
遵循规则:

5.7、相等操作符

相等和不相等 —— 先转换再比较
全等和不全等 —— 仅比较而不转换

5.7.1、相等和不相等

  相等操作符由像个等于号(==)表示,如果两个操作数相等,返回 true
不相等操作符由叹号后等等于号(!=)表示,如果两个操作数不相等,返回 true。
这两个操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性。

转换不同的数据类型是,遵循规则:

相等和不相等操作符在进行比较时遵循规则:

特殊情况:

表达式
null == undefined true
"NaN" == NaN false
5 == NaN false
NaN == NaN false
NaN != NaN true
false == 0 true
true == 1 true
true == 2 false
undefined == 0 false
null == 0 false
"5" == 5 true
5.7.2、全等和不全等

  全等操作符由 3 个等于号(===)表示,只在两个操作数未经转换就相等的情况下返回 true。

var result1 = ("55" == 55);   // true, 因为转换后相等
var result2 = ("55" === 55);  // false, 因为不同的数据类型不相等

不全等操作符由一个叹号后跟两个等于号(!==)表示。

提示: null == undefined;     // true
      null === unefined;     // false, 类型不同

由于相等和不相等操作符存在类型转换问题,而为了保持代码中数据类型的完整性,推荐使用全等和不全等操作。

1.5.8、条件操作符
variable = boolean_expression ? true_value : false_value;

5.9、赋值操作符

  简单的赋值操作符由等于号(=)表示,其作用就是把右侧的值赋给左侧的变量。
  在等于号(=)前面添加乘性操作符、加性操作符或位操作符,就可以完成复合赋值操作。复合赋值操作相当于常规表达式的简写形式。

var num = 10;
num = num + 10;   =>   num += 10;

复合赋值操作符:

复合赋值操作符的主要目的是简化赋值操作,使用它们不会带来任何性能的提升。

5.10、逗号操作符

使用逗号操作符可以在一条语句中执行多个操作。

var num1 = 1, num2 = 2, num3 = 3;

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

var num = (1, 2, 3, 4, 5);    // num 值为 5

6、语句

6.1、if 语句

if (condition) {
    statement1 
} else {
    statement2
}

6.2、do-while 语句

  do-while 语句是一种后测试循环语句,即只有在循环体中的代码块执行之后,才会测试出口条件。换句话说,在对条件表达式求值之前,循环体内的代码至少会被执行一次。
语法:

do {
    statement
} while (expression);

expression 为 true时,继续循环,为 false时,跳出循环。

6.3、 while 语句

  while 语句属于前测试循环语句,也就是说,在循环体内的代码被执行之前,就会对出口条件求值,因此,循环体内的代码有可能永远不会被执行。
语法:

while (expression) {
    statement
}

6.4、for 语句

  for 语句也是前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行的代码的能力。
语法:

for (initialization; expression; post-loop-expression) {
    statement
}

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

6.5、for-in 语句

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

for (property in expression) {
    statement
}

6.6、 label 语句

使用 label 语句可以在代码中添加标签。
语法:

label: statement

示例:

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

  定义的 start 标签可以在将来由 break 或 continue 语句引用。加标签的语句一般都要与 for 语句等循环语句配合使用。

6.7、break 和 continue 语句

break 和continue 语句用于在循环中精确地控制代码的执行。
break 语句会立即退出循环,强制继续执行循环后面的语句。
continue 语句会立即退出循环,从循环的顶部继续执行。

// break 语句
var num = 0;
for (var i = 1; i < 10; i++) {
    if (i % 5 == 0) {
        break;
    }
    num++;
}
console.log(num);   // 4

// continue 语句
var num = 0;
for (var i = 1; i < 10; i++) {
    if (i % 5 == 0) {
        continue ;
    }
    num++;
}
console.log(num);   // 8

不论是 break 语句还是 continue 语句,都会立即退出当前循环,所以 i = 5 后的 num++ 都不再执行。

  break 和 continue 语句都可以和 label 语句联合使用,从而返回代码中特定的位置。这种联合使用的情况多发生在循环嵌套的情况下。
示例:

var num = 0;
outermost: 
for (var i = 0; i < 10; i++) {
    for (lei j = 0; j < 10; j++) {
        if (i == 5 && j == 5) {
            break outermost;    // num 55
            // continue outermost;    // num 95
        }
        num++;
    }
}
console.log(num);   

建议:使用 label 语句,一定要使用描述性的标签,同时不要嵌套过多的循环。

6.8、with 语句

with 语句的作用是将代码的作用域设置到一个特定的对象中。
语法:

with (expression) {
    statement
}

定义 with 语句的目的主要是为了简化多次编写同一个对象的工作
示例:

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 语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序是,不建议使用 with 语句。

6.9、switch 语句

switch 语句与 if 语句的关系最为密切,是一种流控制语句。

switch (expression) {
    case value:  statement
        break;
    case value:  statement
        break;
    case value:  statement
        break;
    default: statement
}

  switch 语句中的每一种情形(case)的含义是:“如果表达式等于这个值(value),则执行后面的语句(statement)”。
  break 关键字会导致代码执行流跳出 switch 语句,如果省略break关键字,就会导致执行完当前 case 后,继续执行下一个 case。
  最后的 default 关键字则用于在表达式不匹配前面任何一种情形的时候,执行机动代码(因此,也相当于一个 else 语句)。

合并多种情形:

switch (i) {
    case 25:  
    case 35:  
        console.log("25 or 35");
        break;
    case 45:  
        console.log("45");
        break;
    default: 
        console.log("other");
}

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

7、函数

  通过函数可以封装任意多条语句,并可以在任何地方、任何时候调用执行。ECMAScript 中的函数使用 function 关键字来声明,后跟一组参数以及函数体。
语法:

// 声明函数
function functionName (arg0, arg1, ..., argN) {
    statements
}
functionName (); // 调用函数
function sum (num1, num2) {
    return num1 + num2;  // 通过 return 后跟要返回的值来实现返回值
}

  这个函数会在执行完 return 语句后立即停止并退出。因此,位于 return 语句之后的任何代码都永远不会执行。
  return 语句也可以不带任何返回值。这种情况下,函数在停止执行后将返回 undefined 值。这种用法一般在需要提前停止函数执行而又不需要返回值的情况下。

严格模式对函数有一些限制:

如果发生以上情况,就会导致语法错误,代码无法执行。

7.1、理解参数

  ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型。也就是说,即使你定义的函数只接受两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传参数。

  原因:ECMAScript 中的参数在内部是用一个数组来表示的,函数接收到的始终都是这个数组,而不关心数组中包含哪些参数。

  在函数体内部可以通过 arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。

  其实,arguments 对象只是与数组类似(并不是 Array 的实例),因为可以使用方括号语法访问它的每一个元素(第一个元素是 arguments[0]),使用 length 属性来确定传递进来多少个参数。

function sayHi (name, message) {
    console.log("hello " + name + "," + message);
}

function sayHi () {
    console.log("hello " + arguments[0] + "," + arguments[1]);
}
// ECMAScript 函数中命名的参数只是提供便利,不是必需的

  通过访问 arguments 对象的 length 属性可以获知有多少个参数传递给了函数。可以利用这个特点来实现不同的功能。

function doAdd () {
    if (arguments.length === 1) {
        console.log(arguments[0] + 10); 
    } else if (arguments.length === 2) {
        console.log(arguments[0] + arguments[1]); 
    }
}

arguments 对象可以与命名参数一起使用。

function doAdd (num1, num2) {
    if (arguments.length === 1) {
        console.log(num1 + 10); 
    } else if (arguments.length === 2) {
        console.log(arguments[0] + num2); 
    }
}

在非严格模式下:
arguments 的值永远与对应命名参数的值保持同步。

function doAdd (num1, num2) {
    arguments[1] = 10; 
    console.log(num2);
}

doAdd(1);     // undefined
doAdd(1, 2);  // 10

  这并不是说读取这两个值回访问相同的内存空间,num2 和 arguments[1] 的内存空间是独立的,但它们的值会同步。

  但如果只传入一个参数,那么为了 arguments[1] 设置的不会反应到命名参数中。这是因为 arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时命名参数的个数决定的。

  没有传递值的命名参数自动被赋予 undefined 值,就像定义变量没有初始化一样。

  严格模式上述赋值无效, 修改 arguments[1] 的值不会影响 num2 的值。

ECMAscript 中的所有参数传递都是值,不能通过引用传递参数。

7.2、没有重载

  ECMAScript 中定义同名函数,后定义的覆盖先定义的函数,调用函数时仅执行后面的方法。

重载函数:在相同的声明域中的函数名相同的,而参数表不同的,即通过函数的参数表而唯一标识并且来区分函数的一种特殊的函数。

小结

  JavaScript 的核心语言特性在 ECMA-262 中是以名为 ECMAscript 的伪语言的形式定义的。
  ECMAscript 中包含了所有基本的语法、操作符、数据类型以及完成基本的计算任务所必须的对象,但没有对取得输入和产生输出的机制作出规定。

ECMAscript 中的基本要素:

上一篇 下一篇

猜你喜欢

热点阅读