1.null是不是对象,为什么?
在JavaScript中,null
是一个特殊的字面量,它代表“无”或“空值”。尽管历史上由于语言设计的一个错误,typeof null
返回的结果是 "object"
,实际上 null
并不是一个对象。它是一个原始值(primitive value),就像 undefined
、number
、string
、boolean
和 symbol
一样。
这个行为是JavaScript最初版本中的一个错误,并且因为向后兼容性的原因一直保留了下来。在实际编程中,你应该将 null
视作表示没有值的特殊关键字,而不是一个对象。当你想表达一个变量应该存储一个对象,但是当前还没有对象赋给它时,可以使用 null
。
2.如何判断一个对象的时候排除null
如果你需要检测一个变量是否是 null
,你应该直接使用严格等于操作符 ===
来比较:
if (variable === null) {
// 变量是null
}
这种方式可以准确地检测出一个变量是否确实是 null
,而不会与其他可能导致 typeof
返回 "object"
的值混淆。
3.const,let,var定义一个变量的时候,底层是如何实现的
var
- 变量提升(Hoisting):使用
var
关键字声明的变量会在代码执行前进行提升,这意味着它们可以在声明之前被引用,此时它们的值是undefined
。 - 函数作用域(Function Scope):
var
声明的变量具有函数作用域,即它们在声明它们的函数内以及嵌套的任何函数内都是可见的。 - 全局对象属性:在全局作用域中使用
var
声明的变量会成为全局对象(在浏览器中是window
对象)的属性。
let
- 块级作用域(Block Scope):
let
关键字引入了块级作用域,这意味着变量仅在包含它们的代码块(例如if
语句或for
循环)内部可见。 - 暂时性死区(Temporal Dead Zone, TDZ):在代码块内,从块的开始到
let
声明被初始化的那一行之间的区域被称为暂时性死区。在这个区域内访问变量会导致引用错误。 - 不会成为全局对象的属性:即使在全局作用域中声明,
let
声明的变量也不会成为全局对象的属性。
const
- 块级作用域:与
let
相似,const
也是块级作用域。 - 暂时性死区:
const
声明的变量同样存在于暂时性死区中,直到它们被初始化。 - 不可变绑定:
const
声明的变量必须在声明时初始化,并且之后不能被重新赋值(尽管如果它们指向的是对象,对象本身的内容是可以被修改的)。
底层实现
在底层,JavaScript引擎(如V8、SpiderMonkey、JavaScriptCore等)通常会为变量创建环境记录(Environment Record),这是存储变量绑定的数据结构。引擎在执行代码时会处理作用域链,以确定变量的查找和访问。
- 内存分配:在编译阶段,引擎会为变量分配内存,并在需要的时候创建新的执行上下文(Execution Context)。
- 存储和访问:变量的具体值存储在栈(对于原始值)或堆(对于对象)中。引擎会管理变量的存储,并在代码执行时提供对它们的访问。
- 作用域管理:引擎利用词法作用域(Lexical Scope)来确定变量的可见性范围。
var
、let
和const
有不同的作用域规则,引擎会根据这些规则来维护作用域链。
具体的实现细节可能会根据不同的JavaScript引擎而有所不同。优化技术,如即时编译(JIT),也可能影响变量的存储和访问方式。