JS学习日记(一)数据类型

基本语法

1.与C语言的不同

1.基本定义

  • 变量定义
    	var a = 1 + 3 ;
    
  • 变量提升(输出)
    JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
    var a = 1;
    console.log(a);

上面代码使用console.log方法,在控制台(console)显示变量a的值。

  • 标识符

    • 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)。
    • 第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字0-9
  • 注释

    源码中被 JavaScript 引擎忽略的部分就叫做注释,它的作用是对代码进行解释。JavaScript 提供两种注释的写法:一种是单行 注释,用//起头;另一种是多行注释,放在/**/之间。

    此外,由于历史上 JavaScript 可以兼容 HTML 代码的注释,所以 也被视为合法的单行注释。

    x = 1;< !-- x = 2;
    --> x = 3;
    

    上面代码中,只有x = 1会执行,其他的部分都被注释掉了。

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

2.条件语句

  1. 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)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefinednull,一般将它们看成两个特殊值。
对象是最复杂的数据类型,又可以分成三个子类型。

  • 狭义的对象(object)
  • 数组(array)
  • 函数(function)

狭义的对象和数组是两种不同的数据组合方式,除非特别声明,本教程的“对象”都特指狭义的对象。函数其实是处理数据的方法,JavaScript 把它当成一种数据类型,可以赋值给变量,这为编程带来了很大的灵活性,也为 JavaScript 的“函数式编程”奠定了基础。

2.typeof运算符

JavaScript 有三种方法,可以确定一个值到底是什么类型。

  • typeof运算符
  • instanceof运算符
  • Object.prototype.toString方法

typeof运算符可以返回一个值的数据类型。

数值、字符串、布尔值分别返回numberstringboolean

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位浮点数形式储存,即使整数也是如此。所以,11.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(开区间),超出这个范围的数无法表示。

与数值相关的全局方法
  1. 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
    

如果字符串以0x0X开头,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
  1. 进制转换
//默认十进制
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)
  1. 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
  1. isNaN()
isNaN方法可以用来判断一个值是否为NaNisNaN(NaN) // true
isNaN(123) // false
但是,isNaN只对数值有效,如果传入其他值,会被先转成数值。比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true,这一点要特别引起注意。也就是说,isNaN为true的值,有可能不是NaN,而是一个字符串。

isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true
出于同样的原因,对于对象和数组,isNaN也返回trueisNaN({}) // true
// 等同于
isNaN(Number({})) // true

isNaN(['xzy']) // true
// 等同于
isNaN(Number(['xzy'])) // true
但是,对于空数组和只有一个数值成员的数组,isNaN返回falseisNaN([]) // 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;
}
  1. isFinite()
    返回一个布尔值
isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值