深挖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
- 第二个题 复杂数据类型 的判断 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