瓦由 發表於 2022-9-10 01:05:00

关于 JavaScript 中 null 的一切

<blockquote>
<p>原文地址:Everything about null in JavaScript</p>
</blockquote>
<blockquote>
<p>原文作者:Dmitri Pavlutin</p>
</blockquote>
<blockquote>
<p>译者:Gopal</p>
</blockquote>
<p><code>JavaScript</code> 有两种类型:原始类型(<code>strings, booleans, numbers, symbols</code>)和对象</p>
<p>对象是一个复杂的数据结构。最简单的 <code>JavaScript</code> 对象是普通对象 —— 键和相关值的集合</p>
<pre><code class="language-js">let myObject = {
name: 'Eric Cartman'
};
</code></pre>
<p>但是很多情况下不能创建一个对象。在这种情况下,<code>JavaScript</code> 提供了一个特殊的值 <code>null</code> —— 表示缺少对象</p>
<pre><code class="language-js">let myObject = null;
</code></pre>
<p>在这篇文章中,你将学习关于 <code>JavaScript</code> 中的 <code>null</code> 的一切: 它的含义,如何检测它,<code>null</code> 和 <code>undefined</code> 之间的区别,以及为什么大量使用 <code>null</code> 会造成代码维护困难等</p>
<h2 id="1null-的概念">1.null 的概念</h2>
<p><code>JavaScript</code> 规范中这么描述 <code>null</code></p>
<blockquote>
<p>null 是一种原始类型,表示有意不包含任何对象值</p>
</blockquote>
<p>如果您看到 <code>null</code>(分配给变量或由函数返回),那么在那个位置原本应该是一个对象,但由于某种原因,一个对象没有创建</p>
<p>比如,函数 <code>greetObject()</code> 创建对象,但也可以在无法创建对象时返回 <code>null</code>:</p>
<pre><code class="language-js">function greetObject(who) {
if (!who) {
    return null;
}
return { message: `Hello, ${who}!` };
}

greetObject('Eric'); // =&gt; { message: 'Hello, Eric!' }
greetObject();       // =&gt; null
</code></pre>
<p>当上面的函数中传入一个字符串参数时,如预期的,函数返回一个对象 <code>{ message: 'Hello, Eric!' }</code></p>
<p>但是,函数中不传任何参数时,该函数返回 <code>null</code>。返回 <code>null</code> 是合理的,因为 <code>who</code> 参数没有值,导致 <code>greeting</code> 对象无法创建</p>
<h3 id="11-null-的一个比较贴切的比喻">1.1 null 的一个比较贴切的比喻</h3>
<p>考虑关于 <code>null</code> 的一个比较贴切的比喻,你可以把变量想象成一个盒子。就像变量可以容纳对象一样,盒子也可以容纳像茶壶等的物品</p>
<p>但一旦你收到一个盒子,打开它,什么也没有!有人弄错了,给了你一个空盒子。该盒子不包含任何内容,或者换句话说,它包含一个 <code>null</code> 值</p>
<h2 id="2-如何去检测-null">2. 如何去检测 null</h2>
<p>检查 <code>null</code> 好方法是使用严格相等运算符</p>
<pre><code class="language-js">const missingObject = null;
const existingObject = { message: 'Hello!' };

missingObject=== null; // =&gt; true
existingObject === null; // =&gt; false
</code></pre>
<p><code>missingObject === null</code> 的结果为 <code>true</code>,因为 <code>missingObject</code> 变量包含一个 <code>null</code> 值。如果变量包含非空值,比如对象,则表达式 <code>existingObject === null</code> 的结果为 <code>false</code></p>
<h3 id="21-null-是一个假值">2.1 null 是一个假值</h3>
<p><code>null</code> 与 <code>false</code>、0、"、<code>undefined</code>、<code>NaN</code> 都是假值。如果在条件语句中遇到它们,那么 <code>JavaScript</code> 将把它们强制为 <code>false</code></p>
<pre><code class="language-js">Boolean(null); // =&gt; false

if (null) {
console.log('null is truthy');
} else {
console.log('null is falsy'); // logs 'null is falsy'
}
</code></pre>
<h3 id="22-typeof-null">2.2 typeof null</h3>
<p><code>typeof value</code> 类型操作符可以确定值的类型。例如,类型为 15 的是 <code>number</code>,<code>typeof { prop: 'Value' }</code> 等于 <code>object</code>。</p>
<p>有趣的是,<code>null</code> 值类型的结果是什么</p>
<pre><code class="language-js">typeof null; // =&gt; 'object'
</code></pre>
<p>一个缺失的对象类型怎么被判断为 <code>object</code>? 原来 <code>typoef null</code> 作为 <code>object</code> 是早期 <code>JavaScript</code> 实现中的一个错误</p>
<p>不要使用 <code>typeof</code> 操作符检测 <code>null</code> 值。如前所述,使用严格的相等运算符 <code>myVar === null</code></p>
<p>如果你想使用 <code>typeof</code> 去检查一个变量是否是一个对象,你必须排除掉 <code>null</code> 的情况</p>
<pre><code class="language-js">function isObject(object) {
return typeof object === 'object' &amp;&amp; object !== null;
}

isObject({ prop: 'Value' }); // =&gt; true
isObject(15);                // =&gt; false
isObject(null);            // =&gt; false
</code></pre>
<h2 id="3-null-的陷阱">3. null 的陷阱</h2>
<p><code>null</code> 通常会在你希望使用对象的情况下意外出现。然后,如果尝试从 <code>null</code> 中提取属性,<code>JavaScript</code> 会抛出一个错误</p>
<p>让我们再次使用 <code>greetObject()</code> 函数并尝试从返回的对象中访问 <code>message</code> 属性</p>
<pre><code class="language-js">let who = '';

greetObject(who).message;
// throws "TypeError: greetObject() is null"
</code></pre>
<p>因为 <code>who</code> 变量是一个空字符串,所以函数返回 <code>null</code>。当从 <code>null</code> 访问 <code>message</code> 属性时,将抛出类型错误错误</p>
<p>你可以通过使用 可选链操作符 来处理 <code>null</code></p>
<pre><code class="language-js">let who = '';

greetObject(who)?.message ?? 'Hello, Stranger!';
// =&gt; 'Hello, Stranger!'
</code></pre>
<p>或者使用下一节中描述的两种选择。</p>
<h2 id="4-null-的替代方案">4. null 的替代方案</h2>
<p>当你不能构造一个对象时,很容易返回 <code>null</code>。但这种做法也有缺点</p>
<p>一旦 <code>null</code> 出现在执行堆栈中,你总是必须检查它</p>
<p>我们尽量避免返回 <code>null</code>:</p>
<ul>
<li>返回默认对象而不是 <code>null</code></li>
<li>抛出错误而不是返回 <code>null</code></li>
</ul>
<p>让我们回忆一下 <code>greetObject()</code> 函数返回 <code>greeting</code> 对象</p>
<p>当缺少参数时,可以返回一个默认对象,而不是返回 <code>null</code></p>
<pre><code class="language-js">function greetObject(who) {
if (!who) {
    who = 'Stranger';
}
return { message: `Hello, ${who}!` };
}

greetObject('Eric'); // =&gt; { message: 'Hello, Eric!' }
greetObject();       // =&gt; { message: 'Hello, Stranger!' }
</code></pre>
<p>或者抛出一个错误</p>
<pre><code class="language-js">function greetObject(who) {
if (!who) {
    throw new Error('"who" argument is missing');
}
return { message: `Hello, ${who}!` };
}

greetObject('Eric'); // =&gt; { message: 'Hello, Eric!' }
greetObject();       // =&gt; throws an error
</code></pre>
<p>这些实践可以让你完全避免处理 <code>null</code></p>
<h2 id="5-null-vs-undefined">5. null vs undefined</h2>
<p><code>undefined</code> 就是未初始化的变量或对象属性的值</p>
<p>例如,如果在声明变量时没有赋初值,那么访问该变量的结果为 <code>undefined</code></p>
<pre><code class="language-js">let myVariable;

myVariable; // =&gt; undefined
</code></pre>
<p><code>null</code> 和 <code>undefined</code> 之间的主要区别是,<code>null</code> 表示丢失了的对象,而 <code>undefined</code> 表示未初始化的状态</p>
<p>严格相等运算符 === 区分 <code>null</code> 和 <code>undefined</code></p>
<pre><code class="language-js">null === undefined; // =&gt; false
</code></pre>
<p>而松散相等运算符 <code>==</code> 则认为 <code>null</code> 和 <code>undefined</code> 相等</p>
<pre><code class="language-js">null == undefined; // =&gt; true
</code></pre>
<p>我使用松散相等运算符检查变量是否为 <code>null</code> 或 <code>undefined</code></p>
<pre><code class="language-js">function isEmpty(value) {
return value == null;
}

isEmpty(42);                // =&gt; false
isEmpty({ prop: 'Value' }); // =&gt; false
isEmpty(null);            // =&gt; true
isEmpty(undefined);         // =&gt; true
</code></pre>
<h2 id="6-总结">6. 总结</h2>
<p><code>null</code> 是 <code>JavaScript</code> 中的一个特殊值,表示丢失的对象</p>
<p>严格相等运算符判断变量是否为空: <code>variable === null</code>。</p>
<p><code>typoef</code> 操作符用于确定变量的类型(<code>number, string, boolean</code>)。但是,<code>typeof</code> 在 <code>null</code> 情况下会引起误解: <code>typeof null</code> 结果为 <code>object</code></p>
<p><code>null</code> 和 <code>undefined</code> 在某种程度上是等价的,但<code>null</code> 表示一个丢失的对象,而 <code>undefined</code> 表示未初始化状态</p>
<p>尽可能避免返回 <code>null</code> 或将变量设置为 <code>null</code>。因为这种做法会导致 <code>null</code> 值的扩展和需要对 <code>null</code> 的验证。相反,尝试使用具有默认属性的对象,或者甚至抛出错误会是更好的实践</p>
<p>你会使用什么方法来检查 <code>null</code>?</p><br><br>
来源:https://www.cnblogs.com/gopal/p/16675860.html
頁: [1]
查看完整版本: 关于 JavaScript 中 null 的一切