最基础但也最容易被忽略的基本数据类型和引用类型

356 阅读11分钟

数据类型

数据类型分为两种,一种简单数据类型(也称基本数据类型或值类型),包括:

UndefinedNullBooleanNumberString

一种复杂数据类型,包括:

Object -- 是所有对象的基础类型

可以用 typeof 来检测给定变量的数据类型

"undefined" -- 如果这值未定义,或var声明了变量但未对其初始化
"boolean" -- 如果这个值是布尔值
"string" -- 如果这个值是字符串
"number" -- 如果这个值是数值
"object" -- 如果这个值是对象或null(因为null被认为是一个空的对象引用)
"function" -- 如果这个值是函数

引用类型

引用类型的值是引用类型的一个实例。引用类型是一种数据结构,用于将数据和功能组织在一起。 所有对象都具有toLocaleString()、toString()、valueOf()方法。

Object类型

创建对象实例有两种方式:

  • 使用new操作符后跟Object构造函数
var person = new Object()
person.name = 'Lin'
  • 使用字面量表示法
var person = {
    name: 'Lin'
}

访问对象有两种方式:

console.log(person.name) // 点表示法
console.log(person['name']) // 方括号表示法

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

  • constructor -- 保存这用于创建当前对象的函数,对于person而言,构造函数就是Object()
  • hasOwnProperty(propertyName) -- 用于检查给定的属性在当前对象实例中是否存在(而不是在实例的原型中)。propertyName必须是字符串。如person.hasOwnProperty('name') // true
  • isProtoTypeOf(object) -- 用于检查传入的对象是否是当前对象的原型。如person.isProtoTypeOf(Object) // true
  • propertyIsEnumerable(propertyName) -- 用于检查给定的属性是否能够使用for-in语句来枚举,propertyName必须是字符串
  • toLocaleString() -- 返回对象的字符串表示,该字符串与执行环境的地区对应。如当前地区中国:person.toLocaleString() // "[object Object]"
  • toString() -- 返回对象的字符串表示, 如person.toLocaleString() // "[object Object]"
  • valueOf() -- 返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同

Array类型

创建数组有两种方式:

  • 使用Array构造函数
var arr = new Array(3) // 创建包含3项的数组
var _arr = new Array('lin') // 创建包含1项的数组,即字符串"Lin"的数组
var __arr = new Array(4).fill('lin') // 创建多个相同值的数组
  • 使用数组字面量表示法
var arr = ['Lin'] // 创建包含1项的数组

数组特性:

  • 数组存在一个length属性,表示数组长度。它不是只读的,通过设置这个属性,可以从数组的末尾移除项或向数组中添加新项
  • 可以通过Array.isArray(arrName)方法来检测确定某个变量值是不是数组
  • 调用valueOf()返回数组本身,而调用toString()方法会返回数组中国每个值的字符串形式拼接而成的一个以逗号分隔的字符串(会调用数组每一项的toString()方法)
  • 栈方法:栈是一种后进先出的数据结构。数组的push()方法可以接收任意数量的参数,把它们挨个添加到数组末尾,并返回修改后的数组长度。数组的pop()方法会从数组的末尾移除最后一项,减少数组的length值,然后返回移除的项
  • 队列方法:队列是一种后进后出的数据结构。数组的unshift()方法能在数组前端添加任意个项并返回新数组的长度。shift()方法能移除数组中的第一个项并返回该项。结合使用shift()和push()方法,可以像使用队列一样使用数组
  • 重排序方法:reverse()和sort()。reverse()用于反转数组原来的顺序。sort()方法按升序排列数组项,它会调用数组中每个项的toString()方法,然后比较字符串,以确定排序。即使数组中每一项都是数值,比较的也是字符串。sort()方法接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数应该位于第二个之后则返回一个正数。如下比较函数:
function compare(val11, val2) {
    if (val1 < val2) {
        return -1
    } else if (val1 > val2) {
        return 1
    } else {
        return 0
    }
}
  • 操作方法:

concat() 基于当前数组中的所有项创建一个新数组。具体这个方法会先创建当前数组的一个副本,然后将参数添加到这个参数的末尾,最后返回新构建的数组。不改变原数组
slice() 能够给予当前数组中的一或多个项创建一个新数组。它可以接收一或两个参数,即要返回数组的起始和结束位置--但不包括结束位置的项。如果只有一个参数,即返回起始位置到数组结束所有项。不改变原数组
splice() 可以用于删除,插入,替换数组中的项。会返回从原始中删除的项组成的数组,要是没有删除就返回空数组。删除只需指定2个参数:要删除的第一项的位置和要删除的项数;插入需提供3个参数:起始位置、0(要删除的项数)和要插入的项;替换需指定3个参数:起始位置、要删除的项数和要插入的任意数量的项。改变原数组

let arr = [1, 2, 3]
let _arr = arr.concat(4, [5, 6]) // [1, 2, 3, 4, 5, 6]
let arr1 = _arr.slice(0, 5) // [1, 2, 3, 4, 5]
let arr2 = arr.splice(0, 1) // arr2: [1]                 arr: [2, 3] 
let arr3 = arr.splice(0, 0, 9) // arr3: []               arr: [9, 2, 3]
let arr4 = arr.splice(0, 2, 5, 6, 7) // arr4: [9, 2]     arr: [3, 5, 6, 7]
  • 位置方法:indexOf()和lastIndexOf()。他们都接收两个参数,要查找的项和(可选的)表示查找起点位置的索引。都返回要查找的项在数组中的位置,没找的情况返回-1
  • 迭代方法和归并方法 请查看----学习JS原理之数组遍历的几种方式及性能比较

Date类型

可以使用new Date()创建一个日期对象。在不传参的情况下自动获取当前日期和时间。 可以通过Date.parse()或者Date.UTC()返回表示日期的毫秒数。 日期格式化方法:

toDateString() -- 以特定于实现的格式显示星期几、月、日和年
toTimeString() -- 以特定于实现的格式显示时、分、秒和时区
toLocaleDateString() -- 以特定于地区的格式显示星期几、月、日和年
toLocaleTimeString() -- 以特定于地区的格式显示时、分、秒和时区
toUTCString() -- 以特定于实现的格式完整的UTC日期

日期/时间组件常用方法:

getTime() -- 返回表示日期的毫秒数;与valueOf()返回的值相同
setTime(毫秒) -- 以毫秒数设置日期,会改变整个日期
getFullYear() -- 取得4位数的年份
serFullYear(年) -- 设置日期的年份
getMonth() -- 返回日期中的月份,其中0表示一月,11表示十二月
serMonth(月) -- 设置日期的月份
getDate() -- 返回日期月份中的天数(131setDate(日) -- 设置日期中月份的天数。如果传入的值超过了该月中应有的天数,则增加月份
getDay() -- 返回日期中的星期几(0表示星期日,6表示星期六)
getHours() -- 返回日期中的小时数(023getMinutes() -- 返回日期中的分钟数(059getSeconds() -- 返回提起中的秒数(059getMilliseconds() 返回日期中的毫秒数
...

RegExp类型

var expressin = / pattern / flags

其中模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。falgs(标志)部分可以有3个标注:

  • g -- 表示全局模式
  • i -- 表示不区分大小写
  • m -- 表示多行模式
    对于正则表达式还有很多内容,想深入学习的请自行查阅资料学习更多...

Function类型

每个函数都是Function类型的实例。实际上函数是对象,函数名是指针。即函数名仅仅是指向函数的指针,与包含对象指针的其他变量没什么不同。 对于函数的内容还有很多,我将另外写一篇文关于函数以及闭包的总结。

基本包装类型

基本包装类型属于特殊的引用类型,主要区别就是对象的生存期。我们一般不会主动去创建一个基本包装类型,而是在对基本数据类型进行操作时(基本数据类型不是对象,没有属性、方法),后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装类型

var s1 = 'lin'
var s2 = s1.substring(2)

严格来说s1是基本数据类型,是不存在方法的。而后台在执行上述第二行代码时进行了下列操作

  • 创建String类型的实例
  • 在实例上调用指定的方法
  • 销毁这个实例
    可以将以上三个步骤想象成执行下列代码
var s1 = new String('lin')
var s2 = s1.substring(2)
s1 = null

基本包装类型包含:Boolean、Number和String。

  • Boolean类型
var falseValue = false
console.log(falseValue && true) // false
var falseObject = new Boolean(false) // 创建一个boolean包装类型
console.log(falseObject && true) // true  因为falseObject不是基本数据类型false 而且一个包装类型对象,所以是true

typeof操作符对基本数据类型返回"boolean",而对包装类型返回"object"。而且由于Boolean对象是Boolean类型的实例,所以使用instanceof操作符测试Boolean对象会返回true

console.log(typeof falseObject) // object
console.log(typeof falseValue) // boolean
console.log(falseObject instanceof Boolean) // true
console.log(falseValue instanceof Boolean) // false
  • Number类型
var numberObject = new Number(10) // 创建一个number包装类型

使用typeof和instanceof操作符对基本类型和包装类型进行检测时会返回和Boolean一样的结果。

  • String类型
    String类型存在一些方法

    字符方法: charAt()和charCodeAt(),他们都接收一个参数,即基于0的字符位置。charAt()方法以单子符字符串的形式返回给定位置的那个字符。而charCodeAt返回的是字符编码。

    字符串操作方法: slice()、substr()和substring()。这三个方法都会返回被操作字符串的一个子字符串。都接收一个或两个参数。第一个参数表示字符串的开始位置,第二个参数表示子字符串到哪里结束。slice()和substring()的第二个参数指定的是子字符串最后一个字符后面的位置。而substr()的第二个参数指定的则是返回的字符个数。若参数中存在负数,slice()会将传入的负值和字符串长度相加,substr()将负的第一个参数加上字符串的长度,而将负的第二个参数转换为0,substring()会把所有的负值参数都转换成0。他们都不修改原字符串,返回一个基本类型字符串

    var str = "hello world"
    str.slice(-3) // "rld"
    str.substring(-3) // "hello world"
    str.substr(-3) // "rld"
    str.slice(3, -4) // "lo w"
    str.substring(3, -4) // "hel" // 会变成 str.substring(0, 3) 将小的作为开始
    str.substr(3, -4) // "" 空字符串

字符串位置方法: indexOf()和lastIndexOf()
trim()方法: 这个方法创建一个字符串的副本,删除前置及后缀的空格
... 关于String包装类型还有一些其他方法 请自己查阅资料学习更多

单体内置对象

  • Golbal对象
  • Math对象
min() -- 确定一组数值中的最小值
max() -- 确定一组数值中的最大值
ceil() -- 执行向上舍入
floor() -- 执行向下舍入
round() -- 执行标准舍入
random() -- 返回大于等于0小于1的一个随机数
值 = Math.random() * 可能值得总数 + 第一个可能得值

如何理解值类型和引用类型

  • 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中
  • 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本
  • 引用类型的值是对象,保存在堆内存中
  • 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针
  • 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象
  • 确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof操作符

结语

最近正在学习JavaScript高级程序设计3。以上内容主要是来自第三章 3.4数据类型和第五章 应用类型的总结。方便后期巩固。