数据类型整顿

js数据类型为8种
根底类型 undefined,Null,Boolean,String,Number,Symbol,BigInt
援用数据类型为Object,常见的援用类型为Array,RegExp,Date,Math,Function

  1. 根底数据类型存储在栈内存,被援用或者拷贝时,会创立衣蛾齐全相等的变量
  2. 援用类型存储在堆内存,存储的是地址,多个援用指向同一个地址,处于“共享”的状态。

一个对象+function例子

let a = {    nae:'jake',    age:18}function change (e){    e.age = 20    e = {        name :'tom',        age:30    }    return e}let b  = change(a);console.log(b.age)console.log(a.age)

打印后果为

3020

function中第一行代码扭转了a对象的age属性,然而return e把新对象e={name:'tom',age:30}地址返回给了b,如果function没有return,第一行打印会提醒undefined

数据类型检测

第一种检测形式,typeof

typeof 1 // 'number'typeof '1' // 'string'typeof undefined // 'undefined'typeof true // 'boolean'typeof Symbol() // 'symbol'typeof null // 'object',js遗留BUG,不代表null是援用数据类型,也不是对象typeof [] // 'object'typeof {} // 'object'typeof console // 'object'typeof console.log // 'function'

第二种检测形式instanceof

let Human = function(){};let women = new Human()console.log(women instanceof Human) // truelet man  = new String("Human");console.log(man instanceof String) // truelet str = "abc";console.log(str instanceof String) // false

依据instanceof现有的个性,实现一个myinstanceof

function myinstanceof(val,typeName) {    if(typeof val  !== 'object' || val === null) return false    // getPrototypeOf用于拿到参数原型对象    let proto = Object.getPrototypeOf(val);    while(true){        if(proto === null)  return false;        if( proto === typeName.prototype) return true;        proto = Object.getPrototypeOf(proto)    }}console.log(myinstanceof('123',String))  // falseconsole.log(myinstanceof(new String('123'),String))  // true

以上得悉,typeofinstanceof两种判断类型的形式都存在问题

  1. instanceof 能够精确地判断简单援用数据类型,然而不能正确判断根底数据类型;
  2. typeof 能够判断根底数据类型(null 除外),然而援用数据类型中,除了 function 类型以外,其余的也无奈判断

第三种检测形式Object.prototype.toString

Object.prototype.toString({})       // "[object Object]"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(val) {    let type = typeof val;    // 根底数据类型间接返回    if (type !== "object")        return type    // object    return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 留神正则两头有个空格}

类型转换规定

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

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

Boolean() 办法的强制转换规则
规定:除了 undefined、 null、 false、 ''、 0(包含 +0,-0)、 NaN 转换进去是 false,其余都是 true。

隐式类型转换

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

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

'+' 的隐式类型转换规定

  1. '+' 号操作符,不仅能够用作数字相加,还能够用作字符串拼接。仅当 '+' 号两边都是数字时,进行的是加法运算;如果两边都是字符串,则间接拼接,毋庸进行隐式类型转换。
  2. 如果其中有一个是字符串,另外一个是 undefined、null 或布尔型,则调用 toString() 办法进行字符串拼接;如果是纯对象、数组、正则等,则默认调用对象的转换方法会存在优先级(下一讲会专门介绍),而后再进行拼接。
  3. 如果其中有一个是数字,另外一个是 undefined、null、布尔型或数字,则会将其转换成数字进行加法运算,对象的状况还是参考上一条规定。
  4. 如果其中一个是字符串、一个是数字,则依照字符串规定进行拼接。

Object 的转换规则
对象转换的规定,会先调用内置的 [ToPrimitive] 函数,其规定逻辑如下:

  1. 如果部署了 Symbol.toPrimitive 办法,优先调用再返回;
  2. 调用 valueOf(),如果转换为根底类型,则返回;
  3. 调用 toString(),如果转换为根底类型,则返回;
  4. 如果都没有返回根底类型,会报错。