• 主页
  • 个人简介
    • 圣墨 photo

      圣墨

      一个爱折腾,有诗有远方的人

    • Learn More
    • Github
    • Cnblogs
    • Weibo
  • 文章
    • 所有文章
    • 所有标签
  • Html&Css
  • Javascript
  • 设计模式
  • 前端性能优化
  • 原生实现专题
  • 数据结构与算法
  • Book
  • 面试题
  • 前端工具
  • 随记

《重学前端》-01

19 Jul 2019

Reading time ~1 minute

关于类型,有哪些不知道的细节?

问题

  • 为什么有的编程规范要求用void 0 代替 undefined?
  • 字符串有最大长度吗?
  • 0.1 + 0.2 不是等于0.3吗? 为什么JavaScript里不是这样的?
  • ES6 新加入的Symbol 是个什么东西?
  • 为什么给对象添加的方法能用在基本类型上?

undefined 和 null(为什么有的编程规范要求用void 0 代替 undefined?)

  • Undefined 类型是未定义,它的类型只有一个值,就是undefined,未定义
  • Null 类型也只有一个值,就是null,定义了但是为空
  • undefined 是变量,null 是关键字
  • undefined 是变量,这是JavaScript语言公认的设计失误之一,因为变量会被篡改,所以,为了避免无意中被篡改,使用void 0 来获取undefined值

String (字符串有最大长度吗?)

  • String 有最大长度是2^53-1
  • String 的意义并非“字符串”,而是字符串的UTF16编码

Number(0.1 + 0.2 不是等于0.3吗? 为什么JavaScript里不是这样的?)

  • JavaScript 中Number 类型有18437736874454810627(即2^64-2^53+3)个值
  • 额外的语言场景,可以除以0不会出错
  • NaN
  • Infinity 正无穷
  • -Infinity 负无穷大
  • 区分 +0和-0的方式,正是监测1/x是Infinity还是-Infinity
  • 正确比较小数点方法
Math.abs(0.1+ 0.2 - 0.3) <= Number.EPSILON

// Math.abs() 绝对值
// Number.EPSILON ES6新增  表示可以接受的最小误差范围。

Symbol(ES6 新加入的Symbol 是个什么东西?)(ps: 参考《ECMAScript 6 入门》)

  • Symbol 不是对象,不能使用new命令,不能添加属性, 基本上,它是一种类似于字符串的数据类型。
  • Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示。
  • 如果 Symbol 的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。
  • Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
  • Symbol 值不能与其他类型的值进行运算,会报错。但是,Symbol 值可以显式转为字符串。
  • Symbol 值也可以转为布尔值,但是不能转为数值。
  • Symbol 值作为对象属性名时,不能用点运算符。
  • 在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。
  • Symbol 作为属性名,该属性不会出现在for…in、for…of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名。

Object(为什么给对象添加的方法能用在基本类型上?)

  • (点).运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法

类型转换

  • 臭名昭著的是JavaScript中“==” 实现跨类型比较吗, 属于设计失误

String To Number

  • Number()
  • parseInt()
  • parseFloat()
  • 隐式转换(运算符ps: - * /)

装箱转换

  • 装箱转换:基本类型转换为对应的引用类型的操作称为装箱转换

拆箱转换

  • 对象类型转换为基本数据类型称为拆箱
  • 将引用类型对象转换为对应的值类型对象,它是通过引用类型的valueOf()或者toString()方法来实现的。如果是自定义的对象,你也可以自定义它的valueOf()/tostring()方法,实现对这个对象的拆箱。
var objNum = new Number(123);  
var objStr =new String("123");  

console.log( typeof objNum ); //object
console.log( typeof objStr ); //object

console.log( typeof objNum.valueOf() ); //number
console.log( typeof objStr.valueOf() ); //string
console.log( typeof objNum.toString() ); // string 
console.log( typeof objStr.toString() ); // string
  • 拆箱转换会尝试调用valueOf 和toSting来获得拆箱后的基本类型,如何valueOf 和toString都不存在,或者没有返回基本类型,则会产生类型错误TypeError
    var o = {
        valueOf: () => {
            console.log('valueOf');
            return {}
        },
        toString: () => {
            console.log('toString');
            return {}
        }
    }
    o * 2
    // valueOf
    // toString
    // TypeError  产生错误类型的原因是,虽然o对象中有valueOf 和 toString, 但是没有返回基本类型 
  • ES6 之后,允许对象通过显示指定@@toPrimitive Symbol 来覆盖原有的行为
    var o = {
        valueOf: () => {
            console.log('valueOf');
            return {}
        },
         toString: () => {
            console.log('toString');
            return {}
        }
    }
    o[Symbol.toPrimitive] = () => {
        console.log('toPrimitive');
        return "hello"
    }
    console.log(o + '');
    // toPrimitive
    // hello


javascript  微博  QQ  朋友圈