• JS基础-变量类型和类型转换


    JS 变量类型

    JS中有 6 种原始值,分别是:

    1. boolean
    2. number
    3. string
    4. undefined
    5. symbol
    6. null

    引用类型:

    1. 对象
    2. 数组
    3. 函数

    JS中使用typeof能得到哪些类型?

    其中一个奇怪的 null,虽然是基本变量,但是因为设计的时候null是全0,而对象是000开头,所以有这个误判。

    1. boolean
    2. number
    3. string
    4. undefined
    5. symbol
    6. object
    7. function
    8. bigint

    instanceof 能正确判断对象的原理是什么?

    判断一个对象与构造函数是否在一个原型链上

    const Person = function() {}
    const p1 = new Person()
    p1 instanceof Person // true
    
    var str = 'hello world'
    str instanceof String // false
    
    var str1 = new String('hello world')
    str1 instanceof String // true
    

    实现一个类型判断函数

    1. 判断null
    2. 判断基础类型
    3. 使用Object.prototype.toString.call(target)来判断引用类型

    注意: 一定是使用call来调用,不然是判断的Object.prototype的类型
    之所以要先判断是否为基本类型是因为:虽然Object.prototype.toString.call()能判断出某值是:number/string/boolean,但是其实在包装的时候是把他们先转成了对象然后再判断类型的。 但是JS中包装类型和原始类型还是有差别的,因为对一个包装类型来说,typeof的值是object

    /**
     * 类型判断
     */
    function getType(target) {
      //先处理最特殊的Null
      if(target === null) {
        return 'null';
      }
      //判断是不是基础类型
      const typeOfT = typeof target
      if(typeOfT !== 'object') {
        return typeOfT;
      }
      //肯定是引用类型了
      const template = {
        "[object Object]": "object",
        "[object Array]" : "array",
        // 一些包装类型
        "[object String]": "object - string",
        "[object Number]": "object - number",
        "[object Boolean]": "object - boolean"
      };
      const typeStr = Object.prototype.toString.call(target);
      return template[typeStr];
    }
    

    转Boolean

    以下都为假值,其他所有值都转为 true,包括所有对象(空对象,空数组也转为真)。

    • false
    • undfined
    • null
    • ''
    • NaN
    • 0
    • -0

    对象转基本类型

    对象在转换基本类型时,会调用valueOf, 需要转成字符类型时调用toString

    var a = {
      valueOf() {
        return 0;
      },
      toString() {
        return '1';
      }
    }
    
    1 + a           // 1
    '1'.concat(a)   //"11"
    

    也可以重写 Symbol.toPrimitive ,该方法在转基本类型时调用优先级最高Symbol.toPrimitive 指将被调用的指定函数值的属性转换为相对应的原始值。

    类型转换

    运算中其中一方为字符串,那么就会把另一方也转换为字符串
    如果一方不是字符串或者数字,那么会将它转换为数字或者字符串

    1 + '1' // '11'
    true + true // 2
    4 + [1,2,3] // "41,2,3"
    

    还需要注意这个表达式'a' + + 'b'

    'a' + + 'b' // -> "aNaN"
    

    因为 + 'b' 等于 NaN,所以结果为 "aNaN",你可能也会在一些代码中看到过 + '1' 的形式来快速获取 number 类型。

    JS类型转换规则总结

    JS隐射类型转换

    100 + 问题

    '100' + 100   // "100100"
    
    100 + '100'   // "100100"
    
    100 + true    // 101
    
    100 + false   // 100
    
    100 + undefined //NaN
    
    100 + null    // 100
    

    "a common string"为什么会有length属性

    通过字面量的方式创建:var a = 'string';,这时它就是基本类型值;通过构造函数的方式创建:var a = new String('string');这时它是对象类型。

    基本类型是没有属性和方法的,但仍然可以使用对象才有的属性方法。这时因为在对基本类型使用属性方法的时候,后台会隐式的创建这个基本类型的对象,之后再销毁这个对象

    == 操作符

    对于 == 来说,如果对比双方的类型不一样的话,就会进行类型转换

    判断流程:

    1. 首先会判断两者类型是否相同。相同的话就是比大小了
    2. 类型不相同的话,那么就会进行类型转换
    3. 会先判断是否在对比 null 和 undefined,是的话就会返回 true
    4. 判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
    1 == '1'
          ↓
    1 ==  1
    
    1. 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
    '1' == true
            ↓
    '1' ==  1
            ↓
     1  ==  1
    
    1. 判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断
    '1' == { a: 'b' }
            ↓
    '1' == '[object Object]'
    
    1. 两边都是对象的话,那么只要不是同一对象的不同引用,都为false

    注意,只要出现NaN,就一定是false,因为就连NaN自己都不等于NaN
    对于NaN,判断的方法是使用全局函数 isNaN()

    === 操作符

    不转类型,直接判断类型和值是否相同。
    但是 NaN === NaN 还是false

    {} 等于true还是false

    var a = {};
    
    a == true // -> ?
    a == false // -> ?
    

    答案是两个都为false
    因为 a.toString() -> '[object Object]' -> NaN

    1 与 Number(1)有什么区别

    var a = Number(1) // 1
    var b = new Number(1)  // Number {[[PrimitiveValue]]: 1}
    typeof (a) // number
    typeof (b) // object
    a == b // true
    
    • var a = 1 是一个常量,而 Number(1)是一个函数
    • new Number(1)返回的是一个对象
    • a==b 为 true 是因为所以在求值过程中,总是会强制转为原始数据类型而非对象,例如下面的代码:
    typeof 123 // "number"
    typeof new Number(123) // "object"
    123 instanceof Number // false
    (new Number(123)) instanceof Number // true
    123 === new Number(123) // false
    

    console.log(!!(new Boolean(false))输出什么 [易混淆]

    true
    布尔的包装对象 Boolean 的对象实例,对象只有在 null 与 undefined 时,才会认定为布尔的 false 值,布尔包装对象本身是个对象,对象->布尔 都是 true,所以 new Boolean(false)其实是布尔的 true,看下面这段代码:

    if(new Boolean(false)){
        alert('true!!');
    }
    

    只有使用了 valueOf 后才是真正的转换布尔值,与上面包装对象与原始资料转换说明的相同:

    !!(new Boolean(false))  //true
    (new Boolean(false)).valueOf() //false
    

    如何判断一个数据是不是Array

    • Array.isArray(obj)
      • ECMAScript 5种的函数,当使用ie8的时候就会出现问题。
    • obj instanceof Array
      • 当用来检测在不同的window或iframe里构造的数组时会失败。这是因为每一个iframe都有它自己的执行环境,彼此之间并不共享原型链,所以此时的判断一个对象是否为数组就会失败。此时我们有一个更好的方式去判断一个对象是否为数组。
    • Object.prototype.toString.call(obj) == '[object Array]'
      • 这个方法比较靠谱
    • obj.constructor === Array
      • constructor属性返回对创建此对象的函数的引用

    Object.prototype.toString

    如果是原始类型,他会将原始类型包装为引用类型,然后调用对应方法

    function dd(){}
    var toString = Object.prototype.toString;
    toString.call(dd);          //[object Function]
    toString.call(new Object);  //[object Object]
    toString.call(new Array);   //[object Array]
    toString.call(new Date);    //[object Date]
    toString.call(new String);  //[object String]
    toString.call(Math);        //[object Math]
    toString.call(undefined);   //[object Undefined]
    toString.call(null);        //[object Null]
    toString.call(123)          //[object Number]
    toString.call('abc')        //[object String]
    

    obj.toString() 和Object.prototype.toString.call(obj)

    同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

    这是因为toString为Object的原型方法,而Array ,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。

    输出以下代码运行结果

    1 + "1"
    
    2 * "2"
    
    [1, 2] + [2, 1]
    
    "a" + + "b"
    
    • 1 + "1"
      • 加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来
      • 所以值为:“11”
    • 2 * "2"
      • 乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值
    • [1, 2] + [2, 1]
      • Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。
      • 所以两个数组对象的toString方法相加,值为:"1,22,1"
    • "a" + + "b"
      • 后边的“+”将作为一元操作符,如果操作数是字符串,将调用Number方法将该操作数转为数值,如果操作数无法转为数值,则为NaN。
      • 所以值为:"aNaN"
    今天你学习了吗!!!
  • 相关阅读:
    jQuery获取鼠标事件源
    windows中MongoDB安装和环境搭建
    前端获取后台数据的方法:ajax、axios、fetch
    浅谈:easy-mock的使用
    安全篇-AES/RSA加密机制
    PHP开发api接口安全验证
    Ajax简单实现文件异步上传的多种方法
    PHP7有没有你们说的那么牛逼
    基于laravel框架构建最小内容管理系统
    redis用法分析
  • 原文地址:https://www.cnblogs.com/nayek/p/11729909.html
Copyright © 2020-2023  润新知