深挖JavaScript语法二

作者: 吴少在coding | 来源:发表于2017-12-25 16:58 被阅读39次

    JS一定要抠细节,逻辑性。我们这次探讨 内存 的问题、一个IE的BUG以及深拷贝和浅拷贝,和typeof运算符的小技巧

    在第一集里面知道了7个基本的数据类型
    number string boolean symbol null underdefined object
    那么这七个数据类型如何转换呢

    其他数据类型转string

    • String()函数
    String(0)
    "0"
    String(true)
    "true"
    String(false)
    "false"
    String(null)
    "null"
    String(undefined)
    "undefined"
    String({})
    "[object Object]"
    String({name: 9})
    "[object Object]"
    
    • toString()属性
      注意null和undefined只是两个值,没有toString()属性
    null.toString()
    VM371:1 Uncaught TypeError: Cannot read property 'toString' of null
        at <anonymous>:1:6
    (anonymous) @ VM371:1
    undefined.toString()
    VM400:1 Uncaught TypeError: Cannot read property 'toString' of undefined
        at <anonymous>:1:11
    (anonymous) @ VM400:1
    

    还有一个要注意的

    {}.toString()
    VM91:1 Uncaught SyntaxError: Unexpected token .
    ({}).toString()
    "[object Object]"
    

    其他的都可以

    var a = 8;
    a.toString()
    "8"
    var a = true
    a.toString()
    "true"
    var a = {}
    a.toString()
    "[object Object]"
    
    • 最常见的方法 ' '+
      无敌的方法
    '' +1
    "1"
    ''+ true
    "true"
    ''+ null
    "null"
    ''+ undefined
    "undefined"
    

    其它数据类型转number

    • Number()函数
    Number('fff')
    NaN
    Number('30')
    30
    Number(null) //注意是0
    0
    Number(undefined) //注意是NaN
    NaN
    Number(true)
    1
    Number(false)
    0
    
    • parseInt()和parseFloat()属性
      parseInt()有个大坑,是从左边第一个字符开始看,不是数字,就停下了,而不是我理解 的有几个数字就打印几个数字
    parseInt('122') //默认是十进制
    122
    parseInt('011')
    11
    parseInt('011', 2) //规定是二进制
    3
    parseInt('123', 10)
    123
    parseInt('011', 8) //规定是八进制
    9
    parseInt('A09') //发现第一个字符就不是数字,不往后面判断了
    NaN
    parseInt('09A12')
    9
    parseFloat('11.4')
    11.4
    
    • 没见过的操作 其他数据类型-0
    null-0
    0
    undefined-0
    NaN
    '91' - 0
    91
    '91.09' - 0
    91.09
    'str' - 0
    NaN
    var a = {}
    a-0
    NaN
    var a = '123'
    a-0
    123
    
    • 又是一个没见过的操作 + ''
    +'124'
    124
    +'12.4'
    12.4
    +false
    0
    +true
    1
    +null
    0
    +undefined
    NaN
    

    其它数据类型转成boolean

    注意5个特殊的falsey值,当然了false必然也是falsey值


    0
    NaN
    ' ' 这是空字符串,啥也没有,空格也没有
    null
    undefined


    除了以上6个falsey值,其他的都是true

    • Boolean()函数
    Boolean('')
    false
    Boolean(' ')
    true
    Boolean(0)
    false
    Boolean(NaN)
    false
    Boolean(null)
    false
    Boolean(undefined)
    false
    Boolean([])
    true
    Boolean({})
    true
    Boolean(9)
    true
    Boolean('pp')
    true
    
    • !!的操作
      怎么理解呢,一个!是取反的操作,再加一个就是双重取反,就是我们想要的结果了
    !0
    true
    !1
    false
    
    !!0
    false
    !!NaN
    false
    !!''
    false
    !!null
    false
    !!undefined
    false
    !!1
    true
    !!'pp'
    true
    !![]
    true
    !!{}
    true
    

    四个经典的内存题

    • 粗糙的内存图的引入
      var a = 1 和var a = new Number(1)分别发生了什么
      简单数据类型存在stack中,存储位置是连续的,像弹匣一样,与数据结构中的栈一样,先进后出(FILO),而复杂数据类型存储在heap中,存储位置不连续,与数据结构中的堆一样,是树状的发散结构,这一点超级重要啊。时时刻刻要记着数据结构啊。

    • 第一个题 简单数据类型的判断 a=?

    var a = 1
    b = a
    b = 2
    
    a
    1
    

    答案是a=1


    第一题.png
    • 第二个题 复杂数据类型 的判断 a =?
    var a = {name: 'wushao'}
    b =a
    b={name: 'shao'}
    
    a
    {name: "wushao"}
    

    答案是a={name: 'wushao'},结果不变


    第二题.png
    • 第三个题 复杂数据类型 的判断 a.name=?
    var a = {name: 'wushao'}
    b =a
    b.name = 'qwert'
    
    a.name
    "qwert"
    

    答案是a.name = 'qwert',已经被b.name改变了


    第三题.png
    • 第四个题 复杂数据类型 的判断 a=?
    var a = {name: 'a'}
    var b = a
    b = null
    
    a
    {name: "a"}
    
    

    答案是 a = {name: "a"} 不受b的影响


    第四题.png

    一个很贱的面试题

    var a = {n: 1}
    var b = a
    a.x = a = {n: 2}
    
    alert(a.x) //是啥呢 undefined
    alert(b.x) //是啥呢 [object Object]
    
    面试题.png

    IE6 的关于垃圾回收机制的一个BUG

    有以下情形

    var fn = function( ){ }
    document.body.onclick = fn
    fn = null
    问你 function(){}是不是垃圾
    
    • 第一种情况,你没有关闭这个tab页
      那么function不是垃圾


      是否是一个垃圾.png
    • 第二种情况,我关闭了这个tab页,那么function就是垃圾了


      关闭网页后就是一个垃圾了.png

    IE6的BUG在于,你关闭了网页,但是蓝色圆里面的他不认为是垃圾,除非你关闭浏览器。所以你要在网页关闭的时候手动加上一个

    //onunload不加载,就是关闭了嘛
    window.onunload = function(){
      document.body.onclick = null; //所有的都要有
    }
    

    由以上几个题引出深拷贝和浅拷贝 的问题

    深拷贝是你改变了,原来的不受改变的影响,而浅拷贝会改变原来的属性。
    对于简单类型的数据来说,赋值就是深拷贝。
    对于复杂类型的数据(对象)来说,才要区分浅拷贝和深拷贝。


    深拷贝.png

    typeof运算符的坑

    JavaScript有三种方法,可以确定一个值到底是什么类型。
    typeof 运算符
    instanceof 运算符
    Object.prototype.toString方法

    typeof运算符可以判断你要的值得数据类型,有如下结果
    先看大坑

    typeof null
    "object"
    typeof Function
    "function"
    function f(){}
    typeof f
    "function"
    

    函数竟然是function类型的数据,坑爹啊。
    null竟然是object,尼玛,吓坏了,一查原来是历史遗留问题。

    1995年JavaScript语言的第一版,所有值都设计成32位,其中最低的3位用来表述数据类型,object对应的值是000。当时,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),完全没考虑null,只把它当作object的一种特殊值,32位全部为0。这是typeof null返回object的根本原因。
    为了兼容以前的代码,后来就没法修改了。这并不是说null就属于对象,本质上null是一个类似于undefined的特殊值。

    你只需要记住,null不是对象 !null不是对象! null不是对象!就是一个值null。
    其他的类型是符合预期的

    typeof 123
    "number"
    typeof '123'
    "string"
    typeof true
    "boolean"
    typeof []
    "object"
    typeof {}
    "object"
    

    判断某变量是否存在的两个技巧

    • 下面演示的是第一种方法
    typeof undefined
    "undefined"
    typeof a
    "undefined"
    

    上面的a未声明,直接使用会报错

    a
    VM412:1 Uncaught ReferenceError: a is not defined
        at <anonymous>:1:1
    

    但是用了typeof就可以啦
    可以用来判断某个变量是否声明了

    if (typeof v === "undefined") {
      // ...
    }
    

    除了上述的方法,还有另外一个利用全局对象的属性的方法

    if ('a' in window) {
      // 变量 a 声明过
    } else {
      // 变量 a 未声明
    }
    
    • 区分数组还是对象的技巧
      既然typeof对数组(array)和对象(object)的显示结果都是object,那么怎么区分它们呢?instanceof运算符可以做到。
    var o = {};
    var a = [];
    
    o instanceof Array // false
    a instanceof Array // true
    

    相关文章

      网友评论

        本文标题:深挖JavaScript语法二

        本文链接:https://www.haomeiwen.com/subject/xrplgxtx.html