乐趣区

关于前端:JS基础JS数据类型

JavaScript 数据类型是入门的根底知识点,同时也是最为重要的,咱们经常在代码中遇到边界数据类型条件判断问题,只有解决好能力让咱们的代码更为谨严。

数据类型的品种

JavaScript 是一种弱类型脚本语言,所谓弱类型指的是定义变量时,不须要什么类型,在程序运行过程中会主动判断类型。最新的 ECMAScript 规范定义了 8 种数据类型:蕴含 7 种根底数据类型和 1 种援用类型。

七种根本数据类型为:

  • 布尔值(Boolean),有 2 个值别离是:true 和 false
  • null,一个表明 null 值的非凡关键字。JavaScript 是大小写敏感的,因而 null 与 Null、NULL 或变体齐全不同
  • undefined,和 null 一样是一个非凡的关键字,undefined 示意变量未赋值时的属性
  • 数字(Number),整数或浮点数,例如:42 或者 3.14159
  • 任意精度的整数 (BigInt),能够平安地存储和操作大整数,甚至能够超过数字的平安整数限度
  • 字符串(String),字符串是一串示意文本值的字符序列,例如:”Howdy”
  • 代表(Symbol)(在 ECMAScript 6 中新增加的类型).。一种实例是惟一且不可扭转的数据类型

援用数据类型(Object)又分为 Array – 数组对象、RegExp – 正则对象、Date – 日期对象、Math – 数学函数、Function – 函数对象等常见类型。

其中根底数据类型存储在栈内存,被援用或拷贝时,会创立一个齐全相等的变量。援用类型存储在堆内存,存储的是地址,多个援用指向同一个地址。

数据类型判断

咱们日常工作中常常会用到数据类型的检测办法,以下三种检测办法是咱们常常用到的。

typeof

typeof 1           //'number'
typeof '1'         //'string'
typeof undefined   //'undefined'
typeof true        //'boolean'
typeof Symbol()    //'symbol'
typeof null        //'object'
typeof []          //'object'
typeof {}          //'object'
typeof /^a/g       //'object'
typeof console     //'object'
typeof console.log //'function'
typeof Array       //'function'
typeof Number      //'function'
typeof Object      //'function'
typeof Math        //'object'
typeof RegExp      //'function'
typeof Date        //'function'

以上输入后果,其中前 6 种都是根底数据类型,然而最初 null 的类型为 object,它不正确地表明 null 是一个对象,这是一个谬误,而且无奈修复,因为它会毁坏现有的代码。在 JS 的最后版本中,应用的是 32 位零碎,为了性能思考应用低位存储了变量的类型信息,000 结尾代表是对象,然而 null 示意为全零,所以将它谬误的判断为 object。尽管当初的外部类型判断代码曾经扭转了,然而对于这个 Bug 却是始终流传下来。

援用数据类型中能够看到除了函数像 Array、Date 等函数判断正确,其余都为 object,像数组字面量是无奈判断进去的。

instanceof

通过 instanceof 咱们能判断这个对象是否是之前那个构造函数生成的对象,这样就根本能够判断出这个新对象的数据类型。比方:

let car = new String('car')
car instanceof String // true

那么 instanceof 是怎么实现的呢?

function instanceof(left, right) {
    // 这里先用 typeof 来判断根底数据类型,如果是,间接返回 false
    if(typeof left !== 'object' || left === null) return false;
    // 取得类型的原型
    let prototype = right.prototype
    // 取得对象的原型
    left = Object.getPrototypeOf(left);
    // 判断对象的类型是否等于类型的原型
    while (true) {if (left === null)
            return false
        if (prototype === left)
            return true
        left = Object.getPrototypeof(left);
    }
}

以上能够看出 instanceof 能够精确地判断简单援用数据类型,然而不能正确判断根底数据类型,而 typeof 尽管能够判断根底数据类型(null 除外),然而援用数据类型中,除了 function 类型以外,其余的也无奈判断。为此这两种写法混写的形式能够去做判断,然而还有一种写法比以上两种更好,就是上面的第三种写法。

Object.prototype.toString

Object 的原型有 toString 办法,调用该办法,能够对立返回格局为‘[object Xxx]’的字符串,其中 Xxx 就是对象的类型,Xxx 第一个首字母要大写(留神:应用 typeof 返回的是小写)。对于 Object 对象,间接调用 toString() 就能返回 [object Object];而对于其余对象,则须要通过 call 来调用,能力返回正确的类型信息,如下所示。

Object.prototype.toString.call({})            // "[object Object]"
Object.prototype.toString.call(1)             // "[object Number]"
Object.prototype.toString.call('1')           // "[object String]"
Object.prototype.toString.call(true)          // "[object Boolean]"
Object.prototype.toString.call(function(){})  // "[object Function]"
Object.prototype.toString.call(null)          // "[object Null]"
Object.prototype.toString.call(undefined)     // "[object Undefined]"
Object.prototype.toString.call(/123/g)        // "[object RegExp]"
Object.prototype.toString.call(new Date())    // "[object Date]"
Object.prototype.toString.call([])            // "[object Array]"
Object.prototype.toString.call(document)      // "[object HTMLDocument]"
Object.prototype.toString.call(window)        // "[object Window]"

实现一个数据类型判断办法是如何编写呢?能够看一下

function getType(obj){
  let type  = typeof obj;
  if (type !== "object") {return type;}
  // 对于 typeof 返回后果是 object 的,进行如下的判断,正则返回后果
  return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1'); 
}

getType([])              // "Array" 
getType('123')           // "string" 
getType(window)          // "Window" 
getType(null)            // "Null"
getType(undefined)       // "undefined" 
getType()                // "undefined" 
getType(function(){})    // "function" 
getType(/123/g)          // "RegExp" 

数据类型转换

数据类型转换次要分为强制类型转换和隐式类型转换,其中隐式类型转换最须要重点记忆一下。

强制类型转换

强制类型转换形式包含 Number()、parseInt()、parseFloat()、Boolean() 等。

Number() 办法的强制转换规则:

  • 如果是布尔值,true 和 false 别离被转换为 1 和 0。
  • 如果是数字,返回本身。
  • 如果是 null,返回 0。
  • 如果是 undefined,返回 NaN。
  • 如果是字符串,遵循以下规定:如果字符串中只蕴含数字(或者是 0X / 0x 结尾的十六进制数字字符串,容许蕴含正负号),则将其转换为十进制;如果字符串中蕴含无效的浮点格局,将其转换为浮点数值;如果是空字符串,将其转换为 0;如果不是以上格局的字符串,均返回 NaN。
  • 如果是 Symbol,抛出谬误。
  • 如果是对象,并且部署了 [Symbol.toPrimitive],那么调用此办法,否则调用对象的 valueOf() 办法,而后根据后面的规定转换返回的值;如果转换的后果是 NaN,则调用对象的 toString() 办法,再次按照后面的程序转换返回对应的值。

parseInt() 办法的强制转换规则:

这个办法的规定是:除了字符串参数的第一个字符为数字返回的后果为数字外,其余都是 NAN。

parseFloat()

这个办法的规定和 parseInt 相似,如果给定值能被解析成浮点数,则返回浮点数。如果给定值不能被转换成数值,则会返回 NAN。

Boolean() 办法的强制转换规则:

这个办法的规定是:除了 undefined、null、false、”、0(包含 +0,-0)、NaN 转换进去是 false,其余都是 true。

隐式类型转换

但凡通过逻辑运算符 (&&、||、!)、运算符 (+、-、*、/)、关系操作符 (>、<、<=、>=)、相等运算符 (==) 或者 if/while 条件的操作,如果遇到两个数据类型不一样的状况,都会呈现隐式类型转换。

以“==”和“+”为例重点解说一下隐式转换的规定。

‘==’的隐式类型转换规定:

  • 如果其中一个操作值是 null 或者 undefined,那么另一个操作符必须为 null 或者 undefined,才会返回 true,否则都返回 false。
  • 如果其中一个是 Symbol 类型,那么返回 false。
  • 两个操作值如果为 string 和 number 类型,那么就会将字符串转换为 number。
  • 如果一个操作值是 boolean,那么转换成 number。
  • 如果一个操作值为 object 且另一方为 string、number 或者 symbol,就会把 object 转为原始类型再进行判断(调用 object 的 valueOf/toString 办法进行转换)。

‘+’的隐式类型转换规定:

‘+’号操作符,不仅能够用作数字相加,还能够用作字符串拼接。仅当‘+’号两边都是数字时,进行的是加法运算;如果两边都是字符串,则间接拼接,毋庸进行隐式类型转换。当然除了数字和字符串外,还有一些其余的类型规定,如下所示:

  • 如果其中有一个是字符串,另外一个是 undefined、null 或布尔型,则调用 toString() 办法进行字符串拼接。
  • 如果其中有一个是数字,另外一个是 undefined、null、布尔型或数字,则会将其转换成数字进行加法运算。
  • 如果其中一个是字符串、一个是数字,则依照字符串规定进行拼接。
  • 如果其中有一个是字符串,另外一个是对象的话,对象转换的规定,1、如果部署了 Symbol.toPrimitive 办法,优先调用再返回。2、调用 valueOf(),如果转换为根底类型,则返回。3、调用 toString(),如果转换为根底类型,则返回。4、如果都没有返回根底类型,会报错。

以上就是数据类型局部相干的内容了,作为前端开发人员还是要致力扎实基本功。

退出移动版