数据类型转换
任意类型转string:
// 使用变量属性 toString(),null,undefined等不可用
(1).toString()
"1"
// 与空字符串相加,推荐
1 + ""
"1"
// 使用 String()
window.String(1)
"1"
任意类型转boolean:
// 使用Boolean()
Boolean(1)
true
Boolean(0)
false
Boolean(undefined)
false
// 两次取反
!!NaN
false
!!1
true
其他类型转boolean后值为false的只有5种情况:null
,undefined
,0
,""
,NaN
,这五个由称作falsy值
字符串转number:
// Number()
Number('1')
1
// parseInt()
parseInt('1')
1
parseInt('a1')
NaN
parseInt('1a')
1
// parseFloat()
parseFloat('1')
1
// 与 0 相减
'1' - 0
1
// 取正值
+ '1'
1
引用
js数据在存储简单类型的数据时(即通常情况下的非object类型数据),都放在stack内存中,而复杂类型数据(object)存在heap内存中。因此在定义一个对象时(如var a = {a: 'b'}
),变量a实际上是一个对象(object)的引用,换言之,即在取值时是通过stack中存储的地址来“间接”的获取值,而不是像简单类型那样直接获取。
接下来就通过几个示例来理解数据存储
// 简单类型存储
var a = 1, b = a
b === 1
true
// 改变b,a的值并不会改变,因为简单类型存储的值而不是引用
b = 2
a === 1
true
// 替换引用 1
// 执行后 {name: 'foo'} 被两个变量引用
var a = {name: 'foo'}, b = a
// 这里是用 {name: 'bar'} 替换了b的先前的引用 {name: 'foo'},而不是修改了先前的引用
b = {name: 'bar'}
a.name=== 'foo'
true
// 替换引用 2
var a = {name: 'foo'}, b = a
// 同样的,这里用null替换了b的先前的引用 {name: 'foo'},所以a的引用还是不变
b = null
a.name === 'foo'
true
// 替换引用 3
var fn = function(){}
document.body.onclick = fn
fn = null
document.body.onclick === null
false
// 修改引用
var a = {name: 'foo'}, b = a
// 这里修改的是引用的内部值,而a,b引用了同一个对象,所以a.name也跟着变更
b.name = 'bar'
a.name === 'bar'
true
// 让人头大的引用
var a = {name: 'foo'}, b = a
// 此处的坑在于,a.x 的 a 是赋值前就确定的,那么这一句就相当于下面两句
// > a.x = {name: 'bar'}
// > a = {name: 'bar'}
// 执行结果
// a -> {name: 'bar'}; b -> {name: 'foo', x: {'name': 'bar'}}
a.x = a = {name: 'bar'}
a.x === undefined
true
b.x.name === 'bar'
true
引用自身
// 这种引用自身的方法无效,因为a先前没有被定义,所以是undefined
var a = {name: 'foo', self: a}
a.self === undefined
true
// 正确方式
var a = {name: 'foo'}
a.self = a
// 成功引用自身
a.self
{name: "foo", self: {…}}
a.age = 18
a.self
{name: "foo", self: {…}, age: 18}
// 可以“无限”self下去
a.self.self.self.name
"foo"
垃圾回收,简而言之没有被引用的值,就会被回收
// 不考虑其他因素(即a,b的值没有其他引用的理想情况下),执行完下面这句后,{name: 'foo'}就变成垃圾了
// 但是变量被回收的具体时间取决与浏览器的回收策略
var a = {name: 'foo'}, b = {name: 'bar'}, a = b
网友评论