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