基本语法
1.与C语言的不同
1.基本定义
- 变量定义:
var a = 1 + 3 ;
- 变量提升(输出)
JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
var a = 1;
console.log(a);
上面代码使用console.log
方法,在控制台(console)显示变量a的值。
-
标识符
- 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号(
$
)和下划线(_
)。 - 第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字
0-9
。
- 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号(
-
注释
源码中被 JavaScript 引擎忽略的部分就叫做注释,它的作用是对代码进行解释。JavaScript 提供两种注释的写法:一种是单行 注释,用
//
起头;另一种是多行注释,放在/*
和*/
之间。此外,由于历史上 JavaScript 可以兼容 HTML 代码的注释,所以 也被视为合法的单行注释。
x = 1;< !-- x = 2; --> x = 3;
上面代码中,只有x = 1会执行,其他的部分都被注释掉了。
需要注意的是,
-->
只有在行首,才会被当成单行注释,否则会当作正常的运算。
2.条件语句
-
1 条件结构
if
结构先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句。所谓布尔值,指的是 JavaScript 的两个特殊值,true
表示真,false
表示伪。if (布尔值) 语句; // 或者 if (布尔值) 语句;
上面是
if
结构的基本形式。需要注意的是,“布尔值”往往由一个条件表达式产生的,必须放在圆括号中,表示对表达式求值。如果表达式的求值结果为true
,就执行紧跟在后面的语句;如果结果为false
,则跳过紧跟在后面的语句。
…其他情况(循环等)与C语言大致相同,不展开(几乎一模一样)
.
.
.
3.标签label
JavaScript 语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置,标签的格式如下。
label:
语句
标签可以是任意的标识符,但不能是保留字,语句部分可以是任意语句。
标签通常与break语句和continue语句配合使用,跳出特定的循环。
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
上面代码为一个双重循环区块,break命令后面加上了top标签(注意,top不用加引号),满足条件时,直接跳出双层循环。如果break语句后面不使用标签,则只能跳出内层循环,进入下一次的外层循环。
标签也可以用于跳出代码块。
foo: {
console.log(1);
break foo;
console.log('本行不会输出');
}
console.log(2);
// 1
// 2
上面代码执行到break foo,就会跳出区块。
continue语句也可以与标签配合使用。
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) continue top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// i=2, j=0
// i=2, j=1
// i=2, j=2
上面代码中,continue命令后面有一个标签名,满足条件时,会跳过当前循环,直接进入下一轮外层循环。如果continue语句后面不使用标签,则只能进入下一轮的内层循环。
2.数据类型
1.简介
类型 | 意义 |
---|---|
数值(number) | 整数和小数(比如1和3.14) |
字符串(string) | 文本(比如Hello World)。 |
布尔值(boolean) | 表示真伪的两个特殊值,即true(真)和false(假) |
undefined | 表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值 |
null | 表示空值,即此处的值为空。 |
对象(object) | 各种值组成的集合。 |
通常,数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined
和null
,一般将它们看成两个特殊值。
对象是最复杂的数据类型,又可以分成三个子类型。
- 狭义的对象(object)
- 数组(array)
- 函数(function)
狭义的对象和数组是两种不同的数据组合方式,除非特别声明,本教程的“对象”都特指狭义的对象。函数其实是处理数据的方法,JavaScript 把它当成一种数据类型,可以赋值给变量,这为编程带来了很大的灵活性,也为 JavaScript 的“函数式编程”奠定了基础。
2.typeof运算符
JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof
运算符instanceof
运算符Object.prototype.toString
方法
typeof
运算符可以返回一个值的数据类型。
数值、字符串、布尔值分别返回number
、string
、boolean
。
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
function f() {}
typeof f
// "function"
typeof undefined
// "undefined"
//对象返回object
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
利用这一点,typeof
可以用来检查一个没有声明的变量,而不报错。
v
// ReferenceError: v is not defined
typeof v
// "undefined"
上面代码中,变量v
没有用var
命令声明,直接使用就会报错。但是,放在typeof
后面,就不报错了,而是返回undefined
。
实际用处:
// 错误的写法
if (v) {
// ...
}
// ReferenceError: v is not defined
// 正确的写法
if (typeof v === "undefined") {
// ...
}
3.数值
JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1
与1.0
是相同的,是同一个数。
这就是说,JavaScript 语言的底层根本没有整数,所有数字都是小数(64位浮点数)。容易造成混淆的是,某些运算只有整数才能完成,此时 JavaScript 会自动把64位浮点数,转成32位整数,然后再进行运算,参见《运算符》一章的“位运算”部分。
由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。
0.1 + 0.2 === 0.3
// false
0.3 / 0.1
// 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1)
// false
浮点数以IEEE754标准定义,64个二进制位
则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。
与数值相关的全局方法
- parselnt()
parseInt
方法用于将字符串转为整数。
上面代码中,parseInt('123') // 123 //如果字符串头部有空格,空格会被自动去除。 parseInt(' 81') // 81 //如果parseInt的参数不是字符串,则会先转为字符串再转换。 parseInt(1.23) // 1 // 等同于 parseInt('1.23') // 1 /*字符串转为整数的时候,是一个个字符 依次转换,如果遇到不能转为数字的字 符,就不再进行下去,返回已经转好的部分。 */ parseInt('8a') // 8 parseInt('12**') // 12 parseInt('12.34') // 12 parseInt('15e2') // 15 parseInt('15px') // 15
parseInt
的参数都是字符串,结果只返回字符串头部可以转为数字的部分。
如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
。parseInt('abc') // NaN parseInt('.3') // NaN parseInt('') // NaN parseInt('+') // NaN parseInt('+1') // 1
如果字符串以0x
或0X
开头,parseInt
会将其按照十六进制数解析。
如果字符串以0
开头,将其按照10进制解析。
parseInt('0x10') // 16
parseInt('011') // 11
//对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。
parseInt(1000000000000000000000.5) // 1
// 等同于
parseInt('1e+21') // 1
parseInt(0.0000008) // 8
// 等同于
parseInt('8e-7') // 8
- 进制转换
//默认十进制
parseInt('1000') // 1000
// 等同于
parseInt('1000', 10) // 1000
parseInt('1000', 2) // 8
parseInt('1000', 6) // 216
parseInt('1000', 8) // 512
parseInt('10', 37) // NaN
parseInt('10', 1) // NaN
parseInt('10', 0) // 10
parseInt('10', null) // 10
parseInt('10', undefined) // 10
//把该转换的转换了
parseInt('1546', 2) // 1
parseInt('546', 2) // NaN
parseInt(0x11, 36) // 43
parseInt(0x11, 2) // 1
// 等同于
parseInt(String(0x11), 36)
parseInt(String(0x11), 2)
// 等同于
parseInt('17', 36)
parseInt('17', 2)
//上面代码中,十六进制的0x11会被先转为十进制的17,再转为字符串。然后,再用36进制或二进制解读字符串17,最后返回结果43和1。
//对于八进制前缀0,尤其得注意
parseInt(011, 2) // NaN
// 等同于
parseInt(String(011), 2)
// 等同于
parseInt(String(9), 2)
- parseFloat()
//parseFloat方法用于将一个字符串转为浮点数。
parseFloat('3.14') // 3.14
//如果字符串符合科学计数法,则会进行相应的转换。
parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14
//如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。
parseFloat('3.14more non-digit characters') // 3.14
//parseFloat方法会自动过滤字符串前导的空格。
parseFloat('\t\v\r12.34\n ') // 12.34
//如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN。
parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
//上面代码中,尤其值得注意,parseFloat会将空字符串转为NaN。
//这些特点使得parseFloat的转换结果不同于Number函数。
parseFloat(true) // NaN
Number(true) // 1
parseFloat(null) // NaN
Number(null) // 0
parseFloat('') // NaN
Number('') // 0
parseFloat('123.45#') // 123.45
Number('123.45#') // NaN
- isNaN()
isNaN方法可以用来判断一个值是否为NaN。
isNaN(NaN) // true
isNaN(123) // false
但是,isNaN只对数值有效,如果传入其他值,会被先转成数值。比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true,这一点要特别引起注意。也就是说,isNaN为true的值,有可能不是NaN,而是一个字符串。
isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true
出于同样的原因,对于对象和数组,isNaN也返回true。
isNaN({}) // true
// 等同于
isNaN(Number({})) // true
isNaN(['xzy']) // true
// 等同于
isNaN(Number(['xzy'])) // true
但是,对于空数组和只有一个数值成员的数组,isNaN返回false。
isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false
上面代码之所以返回false,原因是这些数组能被Number函数转成数值,请参见《数据类型转换》一章。
因此,使用isNaN之前,最好判断一下数据类型。
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。
function myIsNaN(value) {
return value !== value;
}
- isFinite()
返回一个布尔值
isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true