shaolin

悟已往之不谏,知来者之可追!

0%

深挖JavaScript第二集

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](http://upload-images.jianshu.io/upload_images/5422064-0560e23bd6357f1c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


- 第二个题 复杂数据类型 的判断 a =?

var a = {name: ‘wushao’}
b =a
b={name: ‘shao’}

a
{name: “wushao”}

答案是a={name: 'wushao'},结果不变
![第二题.png](http://upload-images.jianshu.io/upload_images/5422064-156139ea55efe504.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- 第三个题 复杂数据类型 的判断 a.name=?

var a = {name: ‘wushao’}
b =a
b.name = ‘qwert’

a.name
“qwert”

答案是a.name = 'qwert',已经被b.name改变了
![第三题.png](http://upload-images.jianshu.io/upload_images/5422064-95dccf49795dfd5b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- 第四个题 复杂数据类型 的判断 a=?

var a = {name: ‘a’}
var b = a
b = null

a
{name: “a”}

答案是 a  = {name: "a"} 不受b的影响
![第四题.png](http://upload-images.jianshu.io/upload_images/5422064-2f71c0ad29ba7a84.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

如图所示

### 一个很贱的面试题

var a = {n: 1}
var b = a
a.x = a = {n: 2}

alert(a.x) //是啥呢 undefined
alert(b.x) //是啥呢 [object Object]

![面试题.png](http://upload-images.jianshu.io/upload_images/5422064-535a5ce55e971e93.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

大坑之处在于那个a.x一开始浏览器先从左边看的

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

有以下情形

var fn = function( ){ }
document.body.onclick = fn
fn = null
问你 function(){}是不是垃圾

- 第一种情况,你没有关闭这个tab页
  那么function不是垃圾
  ![是否是一个垃圾.png](http://upload-images.jianshu.io/upload_images/5422064-c2d28691f8e0081c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 第二种情况,我关闭了这个tab页,那么function就是垃圾了
  ![关闭网页后就是一个垃圾了.png](http://upload-images.jianshu.io/upload_images/5422064-e569b8f33c9d0b08.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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

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

### 由以上几个题引出深拷贝和浅拷贝 的问题
深拷贝是你改变了,原来的不受改变的影响,而浅拷贝会改变原来的属性。
对于简单类型的数据来说,赋值就是深拷贝。
对于复杂类型的数据(对象)来说,才要区分浅拷贝和深拷贝。
![深拷贝.png](http://upload-images.jianshu.io/upload_images/5422064-ced7663ffb4f6530.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

右边蓝色框才是一个完整的复制

### 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 :1:1


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

if (typeof v === “undefined”) {
// …
}


- 第二个小技巧
  既然typeof对数组(array)和对象(object)的显示结果都是object,那么怎么区分它们呢?instanceof运算符可以做到。

var o = {};
var a = [];

o instanceof Array // false
a instanceof Array // true
```