“特殊”

2018-06-13  本文已影响0人  不知道的是

可以在同一条var命令中声明多个变量。

var a, b;
a // undefined
b // undefined

如果使用var重新声明一个已经存在的变量,是无效的。

var x = 1;
var x;
x // 1

上面代码中,变量x声明了两次,第二次声明是无效的。

但是,如果第二次声明的时候还进行了赋值,则会覆盖掉前面的值。

var x = 1;
var x = 2;

// 等同于

var x = 1;
var x;
x = 2;

标识符

var π = 3.14
π // 3.14

var 临时变量 = 1
临时变量 // 1

注释

--> 这是一条合法的JS注释
<!-- 这是一条合法的JS注释
<!-- 这是一条合法的JS注释 -->

-->只有在行首,才会被当成单行注释,否则会当作正常的运算。

function countdown(n) {
  while (n --> 0) console.log(n)
}
countdown(3) // 2 1 0

上面代码中,n --> 0实际上会当作n-- > 0,因此输出2、1、0。

条件语句

if结构

if (布尔值)
  语句;

if (布尔值) 语句;

if (布尔值) {
  语句;
  ...
}

let x = 2
if (x = 3)  console.log(x)
// 3
if (2 = x) console.log(x)
// Uncaught ReferenceError: Invalid left-hand side in assignment

if...else 结构
else代码块总是与离自己最近的那个if语句配对。

var m = 1;
var n = 2;

if (m !== 1)
if (n === 2) console.log('hello');
else console.log('world');

上面代码不会有任何输出,else代码块不会得到执行,因为它跟着的是最近的那个if语句,相当于下面这样。

if (m !== 1) {
  if (n === 2) {
    console.log('hello');   
  } else {
    console.log('world');
  }
}

switch 结构

var x = 1;

switch (x) {
  case 1:
    console.log('x 等于1');
  case 2:
    console.log('x 等于2');
  default:
    console.log('x 等于其他值');
}
// x等于1
// x等于2
// x等于其他值

switch语句部分和case语句部分,都可以使用表达式。

switch(1 + 3) { // 1 + 3
  case 2 + 2: // 2 + 2
    f();
    break;
  default:
    neverHappens();
}

需要注意的是,switch语句后面的表达式,与case语句后面的表示式比较运行结果时,采用的是严格相等运算符(===),而不是相等运算符(==),这意味着比较时不会发生类型转换。

循环语句

while 循环

while (条件)
  语句;

while (条件) 语句;

while (条件) {
  语句;
}

for 循环

for (初始化表达式; 条件; 递增表达式)
  语句

for (initialize; test; increment) {
  语句
}

for语句的三个部分(initialize、test、increment),可以省略任何一个,也可以全部省略。

for ( ; ; ){
  console.log('Hello World');
}

上面代码省略了for语句表达式的三个部分,结果就导致了一个无限循环。

do…while 循环
do...while循环与while循环类似,唯一的区别就是先运行一次循环体,然后判断循环条件。

do
  语句
while (条件);

do {
  语句
} while (条件);

不管条件是否为真,do...while循环至少运行一次,这是这种结构最大的特点。另外,while语句后面的分号注意不要省略

let w = 5
do {
  w--
  console.log(w) // 4 3 2 1 0 -1
} while(w >= 0);

// 省略分号的测试结果
let v = 10
do {
  v--
  console.log(v) // 9 8 7 6 5 4
} while(v >= 5)

break 语句

var i = 0

while(i < 100) {
  console.log('i 当前为:' + i)
  // 上面代码只会执行10次循环,一旦i等于10,就会跳出循环。
  i++
  if (i === 10) break
}

for (var i = 0; i < 5; i++) {
  console.log(i)
  // 上面代码执行到i等于3,就会跳出循环
  if (i === 3)
    break
}

continue 语句

for (let i = 0; i <= 5; i++) {
  if (i % 2) {
    continue
    // 如果i为奇数,直接进入下一轮循环
  }
  console.log(i) // 0 2 4
}

标签(label)

label:
  语句

标签通常与break语句和continue语句配合使用,跳出特定的循环。

Use label

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

Without label

for (var i = 0; i < 3; i++) {
  for (var j = 0; j < 3; j++) {
    console.log('i=' + i + ', j=' + j);
  }
}

// i=0, j=0
// i=0, j=1
// ... ...
// i=2, j=2

typeof 运算符

typeof  function () {} // "function"
typeof undefined // undefined
typeof [] // "object"
typeof null // "object"

null 和 undefined

Number(null) // 0
Number(undefined) // NaN

布尔值

if ('') console.log('true') // 无输出

整数和浮点数

/**
 * true
 * JS内部,所有数字都以64位浮点数形式储存
 * JavaScript 语言的底层根本没有整数
 */
1 === 1.0

由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。

0.1 + 0.2 === 0.3 // false
0.3 / 0.1 // 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1) // false

/**
 * 精度最多只能到53个二进制位,
 * 这意味着,
 * 绝对值小于等于2的53次方的整数,
 * 即-2的53次方到2的53次方,都可以精确表示。
 */
Math.pow(2, 53) // 9007199254740992

/**
 * 出错
 * 9007199254740992
 */
Math.pow(2, 53) + 1

// 多出的三个有效数字,将无法保存
9007199254740992111
// 9007199254740992000

数值范围

JS能够表示的数值范围为2的1024次方到2的-1023次方(开区间),超出这个范围的数无法表示。

Math.pow(2, 1024) // Infinity 正向溢出
Math.pow(2, -1075) // 0 负向溢出

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324

数值的表示法

.1e-23 // 1e-24

/**
 * 小数点前的数字多于21位
 * 1.2345678901234568e+21
 */
1234567890123456789012

/**
 * 小数点后的零多于5个
 * 3e-7
 */
0.0000003

0.000003 // 0.000003

数值的进制

0xff // 255 16进制
0o377 // 255 8进制
0b11 // 3 2进制

如果八进制、十六进制、二进制的数值里面,出现不属于该进制的数字,就会报错。

/**
 * Uncaught SyntaxError: 
 * Invalid or unexpected token
 */
0xzz  // 16进制出现 z
0o88 // 8进制出现 8
0b22 // 2进制出现 2
/**
 * 通常来说,有前导0的数值会被视为八进制,
 * 但是如果前导0后面有数字8和9,
 * 则该数值被视为十进制。
 * 
 * 前导0表示八进制,处理时很容易造成混乱。
 * ES5 严格模式和 ES6中,已废除这种表示法。
 */

0888 // 888
0777 // 511

特殊数值

正零和负零

-0 === +0 // true
0 === -0 // true
0 === +0 // true

+0 // 0
-0 // 0
(-0).toString() // '0'
(+0).toString() // '0'

(1 / +0) === (1 / -0) // false

NaN

5 - 'x'
// NaN

Math.acos(2) // NaN
Math.log(-1) // NaN
Math.sqrt(-1) // NaN

0 / 0 // NaN

typeof NaN // 'number'

NaN === NaN // false

[NaN].indexOf(NaN) // -1

Boolean(NaN) // false

NaN + 32 // NaN
NaN - 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN

Infinity

Math.pow(2, 1024) // Infinity

0 / 0 // NaN
1 / 0 // Infinity

Infinity === -Infinity // false

1 / -0 // -Infinity
-1 / -0 // Infinity

Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)。

Infinity > 1000 // true
-Infinity < -1000 // true

Infinity与NaN比较,总是返回false。

Infinity > NaN // false
-Infinity > NaN // false

Infinity < NaN // false
-Infinity < NaN // false

parseInt()

parseInt('   81') // 81

如果parseInt的参数不是字符串,则会先转为字符串再转换。

parseInt(1.23) // 1
// 等同于
parseInt('1.23') // 1

parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1

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', 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

parseFloat()

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

参考资料:
JavaScript标准参考教程(alpha)

上一篇 下一篇

猜你喜欢

热点阅读