为什么从函数调用中检查 undefined 会导致 SSR 错误,而不是直接在 React 中使用 `typeof`?

why checking for undefined from a function call causes SSR error, but not directly using `typeof` in react?

任何人都可以帮助解释这种意外行为吗?

我有一个来自 https://typeofnan.dev/using-session-storage-in-react-with-hooks/ 的有效 useSessionStorage 挂钩,如下所示:

import { useState, useEffect } from 'react';

function getSessionStorageOrDefault(key, defaultValue) {
  if (typeof sessionStorage === 'undefined') {
    return defaultValue;
  }
  const stored = sessionStorage.getItem(key);
  if (!stored) {
    return defaultValue;
  }
  return JSON.parse(stored);
}

function useSessionStorage(key, defaultValue) {
  const [value, setValue] = useState(
    getSessionStorageOrDefault(key, defaultValue)
  );

  useEffect(() => {
    sessionStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
}

export default useSessionStorage;

请注意我如何检查以确保 sessionStorage 已定义,以确保它在 SSR 中工作:

  if (typeof sessionStorage === 'undefined') {
    return defaultValue;
  }

现在,当我尝试将 typeof sessionStorage === 'undefined' 替换为对名为 isUndefined 的实用程序方法的调用时,我收到 SSR 错误 sessionStorage is not defined.

这里是isUndefined实用方法

export function isUndefined(value) {
  return typeof value === 'undefined';
}

这里是调用 isUndefined 并且 SSR 不再起作用的修改后的 useSessionStorage 挂钩:

import { useState, useEffect } from 'react';
import { isUndefined } from 'utils/lang';

function getSessionStorageOrDefault(key, defaultValue) {
  if (isUndefined(sessionStorage)) {
    return defaultValue;
  }
  const stored = sessionStorage.getItem(key);
  if (!stored) {
    return defaultValue;
  }
  return JSON.parse(stored);
}

function useSessionStorage(key, defaultValue) {
  const [value, setValue] = useState(
    getSessionStorageOrDefault(key, defaultValue)
  );

  useEffect(() => {
    sessionStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
}

export default useSessionStorage;

为什么 typeof sessionStorage === 'undefined' 有效,但用 isUndefined(sessionStorage) 替换它会导致它不再有效?

这是因为 javascript 的一个基本事实以及我能想到的所有编程语言。当您调用 isUndefined(sessionStorage) 时,您正试图传递由名为 sessionStorage by value to the function isUndefined. In order to do that, the sessionStorage identifier needs to be looked up and its value read, which is of course impossible since it hasn't yet been declared 的标识符标识的内存位置,因此出现错误。

另一方面,typeof 是一个 运算符 。您没有将 sessionStorage 的值传递给它,而是要求它查找该标识符的类型。碰巧 typeof 在传递未声明的标识符时的行为是 return 'undefined' 而不是抛出错误。

最后,值得注意的是已声明但javascript中的未定义变量有一个default valueundefined,因此您 可以 将其传递给函数。

希望以下内容清楚:

function isUndefined(identifier) {
  return typeof identifier === "undefined"
}

let x = true
let y

isUndefined(x) // false
isUndefined(y) // true
isUndefined(z) // Uncaught ReferenceError: z is not defined

如果消息是“z 尚未声明”,可能会更清楚,但希望您现在明白它真正告诉您的是什么。