我想知道JavaScriptnull
和undefined
JavaScript之间的区别。
JavaScript 中的 null 和 undefined 有什么区别?
在 JavaScript 中,undefined
表示变量已经声明但尚未赋值,例如:
var testVar;
alert(testVar); //shows undefined
alert(typeof testVar); //shows undefined
null
是一个赋值。可以将它分配给变量作为无值的表示:
var testVar = null;
alert(testVar); //shows null
alert(typeof testVar); //shows object
从前面的示例中,很明显undefined
和null
是两种不同的类型:undefined
是类型本身(未定义),而null
是对象。
null === undefined // false
null == undefined // true
null === null // true
和
null = 'value' // ReferenceError
undefined = 'value' // 'value'
我从这里选择了这个
未定义值是在变量尚未赋值时使用的原始值。
空值是一个原始值,表示空、空或不存在的引用。
当你通过 var 声明一个变量并且不给它一个值时,它的值将是 undefined。就其本身而言,如果您尝试使用 WScript.Echo() 或 alert() 这个值,您将看不到任何内容。但是,如果您向其附加一个空白字符串,那么它会突然出现:
var s;
WScript.Echo(s);
WScript.Echo("" + s);
您可以声明一个变量,将其设置为空,并且行为是相同的,只是您会看到打印出“空”与“未定义”。这确实是一个很小的差异。
您甚至可以将未定义的变量与 null 进行比较,反之亦然,条件将为真:
undefined == null
null == undefined
然而,它们被认为是两种不同的类型。虽然 undefined 是一种完全属于它自己的类型,但 null 被认为是一个特殊的对象值。您可以通过使用 typeof() 来查看这一点,它返回一个表示变量一般类型的字符串:
var a;
WScript.Echo(typeof(a));
var b = null;
WScript.Echo(typeof(b));
运行上述脚本将产生以下输出:
undefined
object
不管它们是不同的类型,如果您尝试访问其中任何一个的成员,它们的行为仍然相同,例如,它们将抛出异常。使用 WSH,您会看到可怕的“'varname' 为空或不是对象”,如果您很幸运的话(但这是另一篇文章的主题)。
您可以明确地将变量设置为未定义,但我强烈建议您不要这样做。我建议只将变量设置为 null 并为您忘记设置的东西保留未定义的值。同时,我真的鼓励您始终设置每个变量。JavaScript 的作用域链不同于 C 风格的语言,即使是老手也容易混淆,将变量设置为 null 是防止基于它的错误的最佳方法。
您将看到 undefined 弹出的另一个实例是使用删除运算符时。我们这些来自 C 世界的人可能会错误地将此解释为破坏一个物体,但事实并非如此。此操作的作用是从数组中删除下标或从对象中删除成员。对于数组,它不会影响长度,而是现在认为下标未定义。
var a = [ 'a', 'b', 'c' ];
delete a[1];
for (var i = 0; i < a.length; i++)
WScript.Echo((i+".) "+a[i]);
上面脚本的结果是:
0.) a
1.) undefined
2.) c
读取从未存在的下标或成员时,您也会得到 undefined 返回。
null 和 undefined 之间的区别在于:JavaScript 永远不会将任何内容设置为 null,这通常是我们所做的。虽然我们可以将变量设置为 undefined,但我们更喜欢 null 因为它不是我们曾经做过的事情。当您进行调试时,这意味着设置为 null 的任何内容都是您自己做的,而不是 JavaScript。除此之外,这两个特殊值几乎是等效的。
null是一个特殊的关键字,表示没有值。
将其视为一个值,例如:
- “foo”是字符串,
- true 是布尔值,
- 1234是数字,
- null 未定义。
undefined属性表示变量还没有被赋值,包括 null 。喜欢
var foo;
定义的空变量是null
数据类型undefined
它们都代表一个 没有值的变量的值
与
null
不代表字符串没有值-空与字符串
喜欢
var a = '';
console.log(typeof a); // string
console.log(a == null); //false
console.log(a == undefined); // false
现在如果
var a;
console.log(a == null); //true
console.log(a == undefined); //true
但
var a;
console.log(a === null); //false
console.log(a === undefined); // true
所以每个人都有自己的使用方式
undefined使用它来比较变量数据类型
null使用它来清空变量的值
var a = 'javascript';
a = null ; // will change the type of variable "a" from string to object
请仔细阅读以下内容。它应该消除您对JavaScriptnull
和undefined
JavaScript之间差异的所有疑虑。此外,您可以使用本答案末尾的实用程序函数来获取更具体类型的变量。
在 JavaScript 中,我们可以拥有以下类型的变量:
- 未声明的变量
- 已声明但未分配的变量
- 用文字赋值的变量
undefined
- 用文字赋值的变量
null
- 分配有除
undefined
或以外的任何变量的变量null
下面对每一种情况进行一一说明:
未声明的变量
- 只能使用
typeof
返回字符串'undefined'的运算符进行检查 - 无法使用松散相等运算符 (
== undefined
)进行检查,更不用说严格相等运算符 (=== undefined
)
以及if 语句和三元运算符(? :
) — 这些会抛出引用错误
- 只能使用
已声明但未分配的变量
typeof
返回字符串“未定义”==
检查null
退货true
==
检查undefined
退货true
===
检查null
退货false
===
检查undefined
退货true
- 对if 语句和三元运算符( )为假
? :
用文字
undefined
赋值的变量 这些变量的处理方式与已声明但未分配的变量完全相同。用文字赋值的变量
null
typeof
返回字符串“对象”==
检查null
退货true
==
检查undefined
退货true
===
检查null
退货true
===
检查undefined
退货false
- 对if 语句和三元运算符( )为假
? :
分配有除
undefined
或以外的任何变量的变量null
- typeof 返回以下字符串之一:'bigint'、'boolean'、'function'、'number'、'object'、'string'、'symbol'
以下提供了正确检查变量类型的算法:
- 获取
typeof
我们的变量并在它不是“对象”时返回它 - 检查
null
,作为typeof null
回报“对象”,以及 - 使用 switch 语句评估Object.prototype.toString.call(o)以返回更精确的值。
Object
'stoString
方法返回看起来像'[object ConstructorName]'的本地/宿主对象的字符串。对于所有其他对象(用户定义的对象),它总是返回'[object Object]' - 如果最后一部分是这种情况(变量的字符串化版本是'[object Object]')并且参数returnConstructorBoolean是
true
,它将尝试通过toString
-ing 并从那里提取名称来获取构造函数的名称。如果无法访问构造函数,则像往常一样返回'object'。如果字符串不包含其名称,则返回'anonymous'
(支持 ECMAScript 2020 之前的所有类型)
function TypeOf(o, returnConstructorBoolean) {
const type = typeof o
if (type !== 'object') return type
if (o === null) return 'null'
const toString = Object.prototype.toString.call(o)
switch (toString) {
// Value types: 6
case '[object BigInt]': return 'bigint'
case '[object Boolean]': return 'boolean'
case '[object Date]': return 'date'
case '[object Number]': return 'number'
case '[object String]': return 'string'
case '[object Symbol]': return 'symbol'
// Error types: 7
case '[object Error]': return 'error'
case '[object EvalError]': return 'evalerror'
case '[object RangeError]': return 'rangeerror'
case '[object ReferenceError]': return 'referenceerror'
case '[object SyntaxError]': return 'syntaxerror'
case '[object TypeError]': return 'typeerror'
case '[object URIError]': return 'urierror'
// Indexed Collection and Helper types: 13
case '[object Array]': return 'array'
case '[object Int8Array]': return 'int8array'
case '[object Uint8Array]': return 'uint8array'
case '[object Uint8ClampedArray]': return 'uint8clampedarray'
case '[object Int16Array]': return 'int16array'
case '[object Uint16Array]': return 'uint16array'
case '[object Int32Array]': return 'int32array'
case '[object Uint32Array]': return 'uint32array'
case '[object Float32Array]': return 'float32array'
case '[object Float64Array]': return 'float64array'
case '[object ArrayBuffer]': return 'arraybuffer'
case '[object SharedArrayBuffer]': return 'sharedarraybuffer'
case '[object DataView]': return 'dataview'
// Keyed Collection types: 2
case '[object Map]': return 'map'
case '[object WeakMap]': return 'weakmap'
// Set types: 2
case '[object Set]': return 'set'
case '[object WeakSet]': return 'weakset'
// Operation types: 3
case '[object RegExp]': return 'regexp'
case '[object Proxy]': return 'proxy'
case '[object Promise]': return 'promise'
// Plain objects
case '[object Object]':
if (!returnConstructorBoolean)
return type
const _prototype = Object.getPrototypeOf(o)
if (!_prototype)
return type
const _constructor = _prototype.constructor
if (!_constructor)
return type
const matches = Function.prototype.toString.call(_constructor).match(/^function\s*([^\s(]+)/)
return matches ? matches[1] : 'anonymous'
default: return toString.split(' ')[1].slice(0, -1)
}
}