undefined、null、ReferenceError的区别
null表示"没有对象",即该处不应该有值。
典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。
典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
ReferenceError:
不定义就直接用,报错!
接下来是示例演示:
var a = 10;
console.log(a);
console.log(b);
b没有被定义时,输出什么?
答案是,不定义时,会报错。
那么定义之后不赋值会输出什么呢?
let a = 10
let b
console.log(a)
console.log(b)
定义之后不赋值,输出的是undefined
综合完整代码:
let a = 10
let b
let c = []
let d = ''
console.log('a=', a)
console.log('!a=', !a)
console.log('!!a=', !!a)
console.log('!!!a=', !!!a)
console.log('---')
console.log('b=', b)
console.log('!b=', !b)
console.log('---')
console.log('c=', c)
console.log('!c=', !c)
console.log('---')
console.log('d=', d)
console.log('!d=', !d)
console.log('---')
function fun(e) {
console.log('e=', e)
console.log('!e=', !e)
}
fun()
console.log('---')
var g = new Object()
console.log('g.data=', g.data)
console.log('!g.data=', !g.data)
console.log('---')
console.log('Object.getPrototypeOf(Object.prototype)=', Object.getPrototypeOf(Object.prototype))
console.log('!Object.getPrototypeOf(Object.prototype)=', !Object.getPrototypeOf(Object.prototype))
输出:
由此可见
- 第一个
!
取布尔值取反,往后每个!
都是取上一个布尔值再取反。 - 定义了有值就输出该值,没有值就输出undefined
- 空字符串会输出空字符串,空数组就输出空数组
- 在函数中,也算是定义了但没赋值,所以是undefined
- 在Object里,没有被定义的,不知道有没有的子属性,是undefined
- 唯独一个null:
Object.getPrototypeOf(Object.prototype)
关于每个变量的布尔值如下:
let a = 10
let b
let c = []
let d = ''
console.log('a=', a)
console.log('Boolean(a):', Boolean(a)) //true
console.log('---')
console.log('b=', b)
console.log('Boolean(b):', Boolean(b)) //false
console.log('---')
console.log('c=', c)
console.log('Boolean(c):', Boolean(c)) //true
console.log('Boolean(b == c):', Boolean(b == c)) //false
console.log('---')
console.log('d=', d)
console.log('Boolean(d):', Boolean(d)) //false
console.log('Boolean(b == d):', Boolean(b == d)) //false
console.log('---')
function fun(e) {
console.log('e=', e)
console.log('Boolean(e):', Boolean(e)) //false
console.log('Boolean(b == e):', Boolean(b == e)) //true,都是定义了,没赋值
}
fun()
console.log('---')
var g = new Object()
console.log('g.data=', g.data)
console.log('Boolean(g):', Boolean(g)) //true
console.log('Boolean(g.data):', Boolean(g.data)) //false
console.log('Boolean(b == g):', Boolean(b == g)) //false
console.log('---')
console.log('Object.getPrototypeOf(Object.prototype)=', Object.getPrototypeOf(Object.prototype))
console.log('Boolean(Object.getPrototypeOf(Object.prototype)):', Boolean(Object.getPrototypeOf(Object.prototype)))
由此可见,有值为true毋庸置疑,空数组(Array)为true,空对象(Object)为true,其余皆为false。
特别:空对象里面的不知道有没有的属性:false。
空值之间的相互等价判断呢
答案是不同类型的,判为false。都是undefined,判为true。
就像图中,b和g都是Undefined,相等。
其实某种意义上来讲g.data也是定义了没赋值。既然定义了g这个对象,那么里面的属性也一起被定义,但是没有拿出来被赋值。
变量作用域的问题
let a = 10
function fun(e) {
console.log('e=', e)
console.log('a(before):', a)
a = 1
console.log('a:', a)
a = 1
console.log('++a:', ++a)
a = 1
console.log('a++:', a++)
}
fun()
console.log('a(after):', a)
// console.log(e)
运行结果:
如果去掉代码中最后一行的注释,会报错,因为在函数外面不认识e是谁~
++a:先自增,再输出。
a++:先输出,再自增。
如果不给a重新赋值呢?
let a = 10
function fun(e) {
console.log('e=', e)
console.log('a(before):', a)
a = 1
console.log('a:', a)
console.log('++a:', ++a)
console.log('a++:', a++)
}
fun()
console.log('a(after):', a)
// console.log(e)
运行结果:
还是符合刚才得出的结论,第一个,先自增,再输出。第二个,先输出,再自增。执行完之后,此时的a已经变成了3