字符串转换
// 数值
1.toString() // Invalid or unexpected token
(1).toString() // '1'
1..toString() // -> (1.).toString() -> '1'
// 布尔
true.toString() // 'true'
// 对象
obj.toString() // [object Object]
null.toString() // Cannot read property 'toString' of null
undefined.toString() // Cannot read property 'toString' of undefined
其实加个空字符串就好了
1 + '' // '1'
true + '' // 'true'
obj + '' // [object Object]
null + '' // 'null'
undefined + '' // 'undefined'
全局方法,和 + 的效果一样
String(1) // '1'
String(true) // 'true'
String(null) // 'null'
String(undefined) // 'undefined'
布尔转换
Boolean 全局变量
Boolean(1) // true
Boolean(0) // false
Boolean('') // false
Boolean(' ') // true
Boolean(null) // false
Boolean(undefined) // false
Boolean({}) // true
Boolean({name: 'ok'}) // true
两次取反就是 Boolean
!!1 // true
!!0 // false
!!{} // true
!!{name: 1} // true
自动转换布尔
0, NaN, ‘’, null, undefined 五个 falsy 值
- Number
- 0 -> false
- NaN -> false
- String
- ‘’ -> false
- Boolean
- false -> false
- Null
- null -> false
- Undefined
- undefined -> false
- Object
- Object, Array, Function全是 true
数值转换
‘1’ -> 1
Number('1') === 1
parseInt('1', 10) === 1
parseFloat('1.23') === 1.23
- 加数字0
'1' - 0 ==== 1
- 向字符串取正
+ '1' === 1
parseInt()
从头开始parse,能parse多少就parse多少,如果不能parse则返回 NaN
对象转换(内存图)
var a = 1
var b = 2
var c = true
var o = { name: 'frank' }
o.gender = 'male'
栈内存
- 存放简单值:number, string, null, undefined, symbol, boolean
- 如果要改gender,则要将栈其中的数据移位,每加一个数据又要往后移位
- 改进方法:存对象的时候不去存具体数据,而是存一个地址Address,在堆内存中存具体的数据
- 如果现在
o2 = o1
,那么就在栈空间里把 o1 的地址赋值给 o2
堆内存
- 存放复杂类型:object
- 以堆的形式去存放对象的内容
- 堆的存放数据是无序的
Self 的问题(循环引用)
考虑如下代码
var a = {}
a.self = a
a.self.self.slef // Error
a.self // OK
-> 栈里:a 存 {} 对象的地址
-> 堆里:对象里的 self 再存放 {} 对象的地址
面试题
var a(#34) = { n : 1 }
var b(#34) = a(#34)
a(#34).x = a(#54) = { n : 2 }
a(#54).x // undefined
b(#34).x // [object, Object]
- 浏览器看第三行的时候,先从左边看,再从右边算
- 所以当第一次看的时候就确定了
a
的所指向的地址(指向{ n : 1 }
) - 然后当
{ n : 2 }
赋值给a
的时候,改变了 a 所指向的地址(指向{ n : 2 }
- 后面的
a.x = a
就是向{n : 1} 第一个对象
中添加一个x
,这个x
指向{ n : 2 }
- 再后面的
a.x
指的是{ n : 2 }
这个对象(在第三步里改了)
垃圾回收
如果一个对象没有被引用,它就是垃圾,将被回收
面试题
var fun = function(){}
document.body.onclick = fn
fn = null
- 第一行的function不是垃圾,onclick 引用了 function
IE6
有bug,窗口关了不会自动垃圾回收,要这样去解决
window.onunload = function() {
document.body.onclick = null
}
浅拷贝 vs 深拷贝
深拷贝:b变不影响a
- 基本类型赋值就是深拷贝
var a = 1
var b = a
浅拷贝:b变致a变
var a = { name: 'a' }
var b = a
b.name = 'b'
a.name // 'b' -> 被改变了