什么原因在JavaScript中使用null而不是undefined?

时间:2011-07-07 01:01:32

标签: javascript null undefined

我已经写了很长时间的JavaScript了,我从来没有理由使用null。似乎undefined总是更可取,并且以编程方式提供相同的目的。使用null代替undefined的一些实际原因是什么?

15 个答案:

答案 0 :(得分:72)

我真的没有答案,但根据 Nicholas C. Zakas ,他的书"Professional JavaScript for Web Developers"的第30页:

  

定义意义的变量时   以后举行一个对象,它是   建议初始化变量   到null而不是其他任何东西。   这样,您可以显式检查值null以确定是否   该变量稍后已用对象引用填充

答案 1 :(得分:38)

Null和undefined本质上是两个不同的值,意思是相同的。唯一的区别在于约定如何在 系统中使用它们。正如一些人所提到的,有些人使用null表示意义"没有对象"你有时可能获得一个对象,而undefined意味着没有预期的对象(或者有一个错误)。我的问题是完全随意,完全没必要。

也就是说,有一个主要区别 - 未初始化的变量(包括没有传递参数的函数参数等)总是未定义。

这就是为什么在我的代码中我从不使用null,除非我不控制的东西返回null(例如正则表达式匹配)。它的美妙之处在于它将事物简化了很多。我永远不必检查x === undefined || x === null。如果您习惯使用==或简单地使用if(x)......停下来。对于空字符串,!x将评估为true,0,null,NaN - 即您可能不想要的内容。如果你想编写那些不太好的javascript,请始终使用triple equals ===并且永远不要使用null(使用undefined代替)。它会让你的生活变得更轻松。

答案 2 :(得分:11)

您可能会采用此处建议的惯例,但确实没有充分的理由。它的使用不够有意义。

为了使约定有用,首先必须知道被调用的函数遵循约定。然后,您必须显式测试返回的值并决定要执行的操作。如果你得到 undefined ,你可以假设被叫函数知道发生了某种错误。但是如果发生错误,并且函数知道它,并且将它发送到更广泛的环境中是有用的,为什么不使用错误对象呢?即抛出错误?

因此,在一天结束时,除了简单环境中的非常小的程序之外,该约定几乎没用。

答案 3 :(得分:9)

undefined是不存在事物概念的地方;它没有类型,并且在该范围之前从未被引用过; null是已知存在的东西,但它没有价值。

答案 4 :(得分:9)

每个人都有自己的编码方式和他们自己的内部语义,但多年来我发现这是最直观的建议,我给那些提出这个问题的人:如有疑问,请做JavaScript做什么

假设您正在处理对象属性,例如jQuery插件的选项...问问自己JavaScript给出了一个尚未定义的属性的值 - 答案是undefined。因此,在这种情况下,我会使用'undefined'初始化这些类型的事物以与JavaScript保持一致(对于变量,您可以var myVar;而不是var myVar = undefined;)。

现在让我们说你正在进行DOM操作...... JavaScript为不存在的元素分配了什么价值?答案是null。如果您要创建一个占位符变量,稍后将保存对与DOM相关的元素,文档片段或类似内容的引用,那么这是我将初始化的值。

如果你正在使用JSON,那么需要做一个特殊情况:对于未定义的属性值,你应该将它们设置为""null,因为值为{{1}不被认为是正确的JSON格式。

有了这样说,正如之前的一张海报所表达的那样,如果你发现你在蓝月亮中不止一次用undefinednull初始化东西,那么也许你应该重新考虑一下去编写你的应用程序。

答案 5 :(得分:4)

在一天结束时,由于nullundefined都强制使用相同的值(Boolean(undefined) === false && Boolean(null) === false),因此您可以在技术上使用其中任何一项来完成工作。但是,有正确的方法,IMO。

  1. undefined的用法留给JavaScript编译器。

    undefined用于描述不指向引用的变量。这是JS编译器会照顾你的东西。在编译时,JS引擎会将所有提升变量的值设置为undefined。当引擎逐步执行代码并且值变得可用时,引擎将为各个变量分配相应的值。对于那些没有找到值的变量,变量将继续保持对原始undefined的引用。

  2. 如果您明确要将变量的值表示为没有值",则仅使用null。

    正如@ com2gz所述:null用于定义以编程方式为空的内容。 undefined意味着该引用不存在。 null值具有对" no"的定义引用。如果您正在调用对象的不存在属性,那么您将获得undefined。如果我故意将该属性设为空,那么它必须是null,以便您知道它是故意的。

  3. TLDR; 不要使用undefined原语。它是JS编译器在您没有赋值声明变量时或者如果您尝试访问没有引用的对象的属性时将自动为您设置的值。另一方面,当且仅当您有意要求变量具有" no value"时才使用null

    我从来没有明确地将任何内容设置为未定义(我还没有在我与之交互过的许多代码库中遇到过这种情况)。另外,我很少使用null。我使用null的唯一时间是当我想要将函数的参数值表示为没有值时,即:

    function printArguments(a,b) {
      console.log(a,b);
    }
    
    printArguments(null, " hello") // logs: null hello
    

答案 6 :(得分:2)

DOM节点和元素未定义,但可能为null。

  • 元素的最后一个子元素的nextSibling为null。

  • 第一个孩子的previousSibling为null。

  • 如果文档中不存在该元素,则document.getElementById引用为空。

但在这些情况中,没有一个是值未定义;那里没有节点。

答案 7 :(得分:2)

null undefined 的有用属性不符合条件:

> null + 3
3
> undefined + 3
NaN

当我想要关闭时,我会使用null'一个数值, 或初始化一些。我最后一次使用是操纵css变换:

const transforms = { perspective : null, rotateX : null };
// if already set, increase, if not, set to x
runTimeFunction((x) => { trasforms.perspective += x; });
// still useful, as setting perspective to 0 is different than turning it off
runTimeFunction2((x) => { transforms.perspective = null; });

// toCss will check for 'null' values and not set then at all
runTimeFunction3(() => { el.style.transform = toCss(transforms); });

不确定我是否应使用此属性...

答案 8 :(得分:1)

我完全不同意使用null或undefined是不必要的。 undefined是保持整个原型链接过程的东西。 因此,仅使用null的编译器不能检查此属性是否等于null,或者它是否未在端点原型中定义。在其他动态类型语言(例如Python)中,如果您想要访问未定义的属性,它会抛出异常,但对于基于原型的语言,编译器也应该检查父原型,这里是未定义需要最多的地方。

使用null的全部含义只是绑定变量或属性,对象是单例并且具有空虚的含义,并且null用法具有性能目的。这2个代码具有不同的执行时间。

var p1 = function(){this.value = 1};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p1();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)

var p2 = function(){this.value = 1, p.x = null};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p2();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p; 
});
big_array.reduce((sum, p)=> sum + p.value, 0)

答案 9 :(得分:1)

我现在正在解决这个问题,并考虑以下理念:

  1. 任何旨在返回结果的函数如果找不到结果都应返回null
  2. 任何非意图返回结果的函数都会隐式返回undefined。
  3. 对我来说,这个问题很重要,因为任何调用返回结果的函数的人都不应该对是否测试undefined vs null进行测试。

    这个答案并不试图解决:

    1. null vs undefined的属性值
    2. 函数中的变量为null vs undefined
    3. 在我看来,变量是您自己的业务,而不是您的API的一部分,并且任何OO系统中的属性都已定义,因此应定义与未定义的值不同的值(null为已定义,未定义)是访问不在你对象中的东西时得到的。)

答案 10 :(得分:1)

这是一个原因:var undefined = 1是合法的javascript,但var null = 1是语法错误。区别在于null是一种语言关键字,而undefined由于某种原因不是。

如果您的代码依赖于与undefined的比较,就好像它是一个关键字(if (foo == undefined) - 一个非常容易犯的错误),这只会起作用,因为没有人定义了具有该名称的变量。所有代码都容易受到意外或恶意定义具有该名称的全局变量的人的攻击。当然,我们都知道在javascript中无意中定义全局变量是完全不可能的......

答案 11 :(得分:1)

在 JavaScript 中,值 null 表示有意缺少任何对象值。 null 表示缺乏标识,表示变量不指向任何对象。

全局 undefined 属性表示原始值 undefinedundefined 是自动分配给变量的原始值。 undefined 表示引用不存在。

答案 12 :(得分:0)

一些人说可以将对象初始化为null。我只想指出,解构参数默认值不适用于null。例如:

const test = ({ name } = {}) => {
  console.log(name)
}

test() // logs undefined
test(null) // throws error

这需要执行null检查之前才能调用可能经常发生的函数。

答案 13 :(得分:0)

只想补充一点,使用某些javascript库,null和undefined可能会带来意想不到的后果。

例如lodash的get函数,该函数接受默认值作为第三个参数:

const user = {
  address: {
    block: null,
    unit: undefined,
  }
}
console.log(_.get(user, 'address.block', 'Default Value')) // prints null
console.log(_.get(user, 'address.unit', 'Default Value')) // prints 'Default Value'
console.log(_.get(user, 'address.postalCode', 'Default Value')) // prints 'Default Value'

另一个示例:如果在React中使用defaultProps,则如果传递属性null,则不会使用默认属性,因为 null被解释为定义的值。 例如

class MyComponent extends React.Component {
   static defaultProps = {
      callback: () => {console.log('COMPONENT MOUNTED')},
   }
   componentDidMount() {
      this.props.callback();
   }
}
//in some other component
<MyComponent />   // Console WILL print "COMPONENT MOUNTED"
<MyComponent callback={null}/>   // Console will NOT print "COMPONENT MOUNTED"
<MyComponent callback={undefined}/>   // Console WILL print "COMPONENT MOUNTED"

答案 14 :(得分:0)

未知变量:undefined

已知变量但没有值:null

  1. 您从服务器server_object收到一个对象。
  2. 您引用了server_object.errj。它告诉您它是undefined。这意味着它不知道那是什么。
  3. 现在您引用server_object.err。它告诉您它是null。这意味着您引用的是正确的变量,但它为空;因此没有错误。

问题是当您声明不带值(var hello)的变量名时,js声明为undefined:此变量不存在;而程序员通常的意思是:“ null的定义是“我还没有给它赋值”。

因此,程序员的默认行为(将不带值的变量声明为空)与js不一致(将其声明为不存在)。此外,!undefined!null都是true,因此大多数程序员都将它们视为等效。

您当然可以确保始终做var hello = null,但是当他们和!运算符同时对待两者时,大多数人不会乱扔它们的代码,以确保使用故意松散类型的语言进行类型检查undefinednull等价。