【问题标题】:Javascript const coming up as undefined and not undefined in chrome dev consoleJavascript const 在 chrome 开发控制台中显示为未定义而不是未定义
【发布时间】:2017-06-10 23:15:12
【问题描述】:

我有一个 const newProducts 正在返回 undefined,但在 chrome 开发控制台中说它不是未定义的:

它说它在控制台中以黄色突出显示的文本定义,当悬停在它上面时未定义。它不应该是未定义的。我已经逐步完成了代码,map 中的returns 正在返回值。为什么这个const 出现undefined 而不是undefined

searchResults.reducer.js

// @flow
import initialState from '../../config/config'
import {
  FETCH_PRODUCTS_REJECTED,
  UPDATE_SEARCH_RESULTS
} from '../search-page/searchPage.action'
import { SET_SELECTED_SHOP } from '../search-results/searchResults.action'

const searchResults = (
  initialResultsState: [] = initialState.get('searchResults'),
  action: Object): string => {
  switch (action.type) {
    case UPDATE_SEARCH_RESULTS: {
      const newProducts = action.payload.products.map(product => {
        return {
          shop: {
            id: product.shop[0].f1,
            name: product.shop[0].f2,
            coordinate: {
              latitude: product.shop[0].f4,
              longitude: product.shop[0].f3
            },
            selected: false
          },
          products: product.products
        }
      })
      return initialResultsState.set('products', newProducts)
    }
    case SET_SELECTED_SHOP: {
      const newProducts = initialResultsState.get('products').map(product => {
        if (product.shop.id === action.payload) {
          return {
            shop: {
              ...product.shop,
              selected: true
            },
            products: product.products
          }
        } else {
          return {
            shop: {
              ...product.shop,
              selected: false
            },
            products: product.products
          }
        }
      })
      return initialResultsState.set('products', newProducts)
    }
    case FETCH_PRODUCTS_REJECTED: {
      console.log('there was an issue getting products: ',
        action.payload)
      return initialResultsState
    }
    default:
      return initialResultsState
  }
}

export default searchResults

【问题讨论】:

  • 这个 ES2015 是在浏览器中运行,还是转译为 ES5,然后使用源映射进行调试以显示为原始 ES2015?
  • @HuguesMoreau 是 react native 在幕后处理的。我认为它被转译了。

标签: javascript react-native redux react-redux


【解决方案1】:

我认为这是 const 转译的副作用,因为转译后 JS 运行时实际上必须跟踪 2 个不同的变量

React Native 使用 Babel 进行转译 (source, pointing at line in 0.45.1 where it enables block scoping)。

你在不同的块中多次定义同名的常量,在ES2015中可以使用constants are block-scoped,但是在ES5中不存在这个概念,所以这样的常量被转译为具有不同名称的变量

例如,考虑这个 ES2015 sn-p:

const i = Date.now() % 2;
switch(i) {
    case 0: {
        const x = "zero";
        console.log("x", x);
    }
    case 1: {
        const x = "one";
        console.log("x", x);
    }
    default: {
        const x = "wat";
        console.log("x", x);
    }
}

Babel, it gets transpiled(←查看实际操作)到:

"use strict";

var i = Date.now() % 2;
switch (i) {
    case 0:
        {
            var x = "zero";
            console.log("x", x);
        }
    case 1:
        {
            var _x = "one";
            console.log("x", _x);
        }
    default:
        {
            var _x2 = "wat";
            console.log("x", _x2);
        }
}

所以在这个例子中,JS 运行时实际上有 3 个不同的变量来表示x

因此,您可能正在查看带有 foo 的行,您的浏览器通过 source map 显示该行,但在“现实”中,浏览器正在查看的内容可能是 _foo2,因此取决于很多事情(转译设置、源映射生成、Chrome 版本、其余代码、您在调用堆栈中的确切位置...),Chrome 开发工具可能无法跟踪并确定foo_foo 中的哪一个或_foo2 应该在您查看 foo 时选择。

以 ES2015 转译为 ES5 和 source map 的示例:

(行为略有不同,因为它取决于很多参数,但它显示了转译具有相同名称的常量的问题——在另一个测试中,使用不同的转译 + 源映射参数,我设法得到类似于你的情况)


建议

我希望以下内容对 O.P. 来说非常明显,但留在答案中可能会很有用

使用 const 语义,您有 2 个同名的不同常量,位于 2 个不同的块中。在我看来,用块作用域定义一个常量(或使用let而不是var的变量)是有用的,以避免var作用域(作用域到最近的父函数)的意外,但定义变量或2 个相邻块中具有相同名称的常量会引起混淆(无论是否转换)。

决定这两个符号是否代表同一事物会更有意义(由您决定),然后:

  • 如果是这样,请使用let 将它们定义为父作用域的单个变量。

  • 如果不是,请将它们保留为 const,但使用 2 个不同的名称。代码会更清晰,转译后开发工具显示的调试信息应该会更有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-02
    • 2012-01-17
    • 1970-01-01
    相关资源
    最近更新 更多