JavaScript的家族谱(数据类型)

JavaScript.png

今天我们来理理JS的家族谱,也就是数据类型。
本文大部分借鉴阮一峰先生的JS教程内容,用于作者学习。文末有原文链接,给想具体了解更多的朋友学习。

成员的分类

JavaScript这个家族里面一共有七个成员,其中大致分为三类:基本类型、特殊类型和复合类型。

基本类型

基本类型和特殊类型都是最原始的,不能再被分类,可以理解为在这个家族中这些成员是没有单独出去成家立业的,所以都是单身狗。

number

数字类型,这第一条单身狗就是数字了

  1. 表示方式
    就是直接表示和科学计数法两种方式,不过有时候JS会将我们的数值自动转换成科学计数法,就是在你的小数点前面的位数多于21位的时候,还有就是首位是0,后面跟着5个以上的0时候。表示小数的话如果整数位是0,可以不写0。
1234567890123456789012
// 1.2345678901234568e+21
0.0000001 // 1e-7
.1===0.1 // true
  1. 数值的进制
    直接表示的时候也是可以输入十进制之外的进制数的,比如二进制、八进制、十六进制。怎么区分这家伙的进制数呢?
  • 十进制不戴帽子(首位什么也不加)
  • 二进制带个帽子上面写着0B/0b
  • 八进制戴的帽子上面写着0
  • 十六进制的帽子上面写着0X/0x
255 //255
0xff // 255
0377 // 255
0b11 // 3
  1. 数值的储存方式
    这个部分就很复杂了,简单地了解一下,数值的储存方式是64位浮点数来储存的。我们需要特别注意的是,当我们在JS中计算小数时,最后的结果很有可能并不精确,在JS中直接计算小数时要特别小心。

  2. 特殊的值

  • NaN
    当判断一个未知的数据类型是不是数字时,假如不是,就会返回一个特殊的值叫做NaN,意思是非数字。这也是JS中唯一一个谁都不等于的数据,真正的独苗一个,因为他自己也不等于自己。
NaN !== NaN // true
  • Infinity
    这家伙有正负之分,叫做无穷,数学符号是∞
  1. 几个和数字相关的语句
  • parseInt()// 英语的意思是解析整数,能把括号里面的东西转化为字符串,然后读取数字,遇到不是数字的就停止,返回已经读取好的数据。(一定是整数,因为小数点不能转化)
  • parseFloat()//英语的意思是解析浮点数,能把括号里面的东西转化为浮点数,就是能把小数点也识别出来。解析的时候发现解析不了的时候就停下来,返回解析好的数据。
  • isNaN()//这就是判断括号里面的是不是NaN
  • isFinity()//这命令是看数据是不是正常数据,只对+InFinity、-InFinity、NaN、undefined、返回false。
parseInt('123') // 123
parseFloat('3.14') // 3.14
isNaN(NaN) // true
isNaN(123) // false
isFinite(undefined) // false
isFinite(null) // true

string

字符串,我们介绍的第二名成员,是个大明星,平常出门挺拉风,经常带着单引号和双引号两个小弟出门。不过有时候,也想低调点,不带引号也能出现。

  1. 转义--我们已经知道了,表示字符串出场的符号就是单双引号,那么当我们想在字符串里面再使用单双引号时,会造成一定的错误,系统并不知道你是想表示引号结束还是想加入一个引号的字符串。所以必须使用转义来实现。常见的几个转义:
  • /0 表示null
  • /' 表示单引号
  • /" 表示双引号
  • /n 表示换行
  • /r 表示回车
  • // 表示/
console.log('1\n2')
// 1
// 2
  1. / 的作用还有另外这一种, 那就是在后面直接接Unicode码,可以是3个八进制,也可以是两个十六进制,或者4个十六进制。
'\u007A' === 'z' // true
  1. 多行字符串-- 在每一行末尾加上\就可以换行输出字符,但是这样假如\后面有空格,就会报错,所以更合适的写法是'字符'+'字符'的写法。
var longString = 'Long '
  + 'long '
  + 'long '
  + 'string';
  1. 有一些字符识别长度的问题,因为JS发明的时候UTF-8还没有发明出来,所以JS只支持部分支持UTF-16,当我们Unicode码点在U+10000~U+10FFFF时,会错误识别字符长度为2。

  2. Base64转码--两个语句

  • btoa():任意值转化成Base64
  • atob() : Base64转化成原值
    当非ASCⅡ要转入时,要加一层转码如下:
function b64Encode(str) {
  return btoa(encodeURIComponent(str));
}

function b64Decode(str) {
  return decodeURIComponent(atob(str));
}

b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"

boolean

boolean值是我们介绍的第三个基本类型,它的值只有两个,那就是true和false,表示真假。当我们使用判断表达式时,就会返回我们一个布尔值,这里介绍6种值直接转化成false

  • undefined
  • null
  • false
  • 0
  • NaN
  • 空字符串
if ('') {
  console.log('true');
}
// 因为空字符串为false所以,console.log不执行

symbol

是ES6中新来的成员,这里暂时不做介绍。

特殊类型

undefined & null

这是两个双胞胎兄弟,只是名字不同,其他的几乎一模一样,都表示什么都没有,具体含义undefined表示没有定义,null表示空,那么区别是:

  • 当一个变量没有赋值,那么返回undefined
  • 如果想有一个对象,但还没有赋值,推荐使用null
  • 如果有一个非对象,且不想给他赋值,使用undefined(直接不赋值即可)

复合类型

复合类型就一个object(对象),不过这和之前介绍的所有数据类型都不一样,他自己成家立业,家里还有数组(array)、函数(function)和其他的对象。

  1. 定义
    对象的定义方法是{}(在数组中用[]定义,函数是function开头)

  2. 格式 {} 里面是key:value的格式,key一般叫做对象的属性,或者键名,而value一般叫做键值,属性值。

  3. key
    在对象里面所有的key都是字符串格式,如果key名称符合标识符的规则,或者是纯数字,则系统自动添加单引号,可以在对象里面不写单引号。不过在定义之外的区域,除非系统能自动转化,不然还是要加上单引号。

  4. value
    value的值可以是任意的数据类型甚至可以又是一个对象,所以object的内部是非常多样。

  5. 查看
    所有的读取和更改都是在我们知道这个对象有哪些属性的情况下,那么怎么知道这个对象有哪些属性呢?有一种命令:Object.keys(对象)

var obj = {
  key1: 1,
  key2: 2
};

Object.keys(obj);
// ['key1', 'key2']
  1. 读取
    当我们定义好对象之后,我们如何调用这个对象呢?通常情况下我们并不会把对象原模原样地照抄到其他地方,而是使用一个变量来保存我们的对象(想想一个比较多的数组或者函数你粘贴也累呀)。使用赋值语句 变量 = object
var obj = {
  p: 'Hello World'
}
obj.p // "Hello World"
obj['p'] // "Hello World"

可是我们有时候并不想把对象全部拿出来调用,就想拿出其中的一个属性名和属性值修改下。这个时候就使用格式:object['属性名'] 意思是调用对象的某个属性,假如你的属性名符合标识符的命名规则,那么也可以写成object.属性名。

  1. 更改/添加
    对象的属性名和属性值是可以定义后,再进行修改或者添加的。我们按照上述方式读取之後,通过赋值语句添加属性并修改
var obj = {};

obj.foo = 'Hello';
obj['bar'] = 'World';

在这个例子中,原本的对象里面并没有自身的属性存在,在后面我们调用了对象,直接用读取的方式来声明属性名,并且赋值给属性,这样就添加了属性其中。

  1. 删除
    既然有添加,就一定有删除。方式是:调用这对象的具体属性,然后在前面添加delete命令
delete obj.p

不过有些属性是不能删除的,执行这个命令会报错。

  1. 判断属性是否在对象里面
    其实我们通过读取的方式也可以判断属性在不在对象里面,不过这里还有一种方式直接告诉你在还是不在,那就是: 属性名 in 对象 --返回布尔值
var obj = { p: 1 };
'p' in obj // true

要注意的是继承属性也会看到,如果要判断是不是继承属性可以用

obj.hasOwnProperty('属性名')
  1. for···in遍历
    可以将对象每一个属性遍历一次
for (var i in obj) {
  console.log('属性名:', i)
}

不可遍历的属性,则不读。继承属性如果可遍历是是可读的。

  1. with 批量操作
    其实with就是想把一个对象里面的属性在一个代码块操作
var obj = {
  p1: 1,
  p2: 2
}
with (obj) {
  p1 = 4;
  p2 = 5;
}
// 等同于
obj.p1 = 4;
obj.p2 = 5;

但是有个问题在于假如里面没有你要操作的属性,你却写进了with的语句,那就是声明当前作用域的变量了,声明也就算了,好歹你把这个当成属性和属性值加进去呀,但因为是变量,和属性值半毛钱关系都没有,所以属性也没能加进去。也就是说,假如object里面并没有with中你要操作的属性,那么你就等着出bug吧!

说说对象里的函数(这里不谈函数具体的用法)

  1. 没有函数这种数据结构
    函数可以说是对象里面最NB的存在,为什么是对象(object)里面呢?因为他是对象这种数据类型的一种,他本身并不是一种数据类型!!!最厉害的还是我们所说的七种数据类型。那么为啥NB?因为也就是没有这个名分,实力和颜值都让他成为JS里面的一等公民,简直屌丝逆袭的典范。
function f() {}
typeof f
// "function"

typeof是一种查看数据类型的命令,所以从上面你看到了什么,对,function,但是注意,没有function这种数据结构!!!这是一个bug,但是也可以理解为function在JS中的地位几乎和其他数据结构一模一样。

  1. 函数名也能提升
    这是又一个厉害之处,在JS中,用函数命令声明函数时
function f() {}

和变量名一样,会被提升到JS的顶部

  1. 函数内部变量提升
    和全局变量提升一个道理,只不过变成了函数内部的局部变量提升,提到函数的开头,感觉都有自己的小宇宙(作用域)了。

一句话说说对象里的数组(array)

不太准确地描述:属性名是自然数有序序列的字符串的特殊对象。

阮一峰先生的JS教程

你可能感兴趣的:(JavaScript的家族谱(数据类型))