源码分析:为什么 JSON.parse('2382E2') 的结果会是 238200?
-
JSON.parse 的执行流程
- 参考:Node 源码:node/deps/v8/src/json/json-parser.cc
-
- 判断数据类型
constexpr JsonToken GetOneCharJsonToken(uint8_t c) { // clang-format off return c == '"' ? JsonToken::STRING : IsDecimalDigit(c) ? JsonToken::NUMBER : c == '-' ? JsonToken::NUMBER : c == '[' ? JsonToken::LBRACK : c == '{' ? JsonToken::LBRACE : c == ']' ? JsonToken::RBRACK : c == '}' ? JsonToken::RBRACE : c == 't' ? JsonToken::TRUE_LITERAL : c == 'f' ? JsonToken::FALSE_LITERAL : c == 'n' ? JsonToken::NULL_LITERAL : c == ' ' ? JsonToken::WHITESPACE : c == '\t' ? JsonToken::WHITESPACE : c == '\r' ? JsonToken::WHITESPACE : c == '\n' ? JsonToken::WHITESPACE : c == ':' ? JsonToken::COLON : c == ',' ? JsonToken::COMMA : JsonToken::ILLEGAL; // clang-format on }
-
或者是0~9
会当作 JsonToken::NUMBER
-
- 处理不同的数据类型
switch (peek()) { case JsonToken::STRING: Consume(JsonToken::STRING); value = MakeString(ScanJsonString(false)); break; case JsonToken::NUMBER: value = ParseJsonNumber(); break; case JsonToken::LBRACE: { Consume(JsonToken::LBRACE); if (Check(JsonToken::RBRACE)) { // TODO(verwaest): Directly use the map instead. value = factory()->NewJSObject(object_constructor_); break; } // Start parsing an object with properties. cont_stack.emplace_back(std::move(cont)); cont = JsonContinuation(isolate_, JsonContinuation::kObjectProperty, property_stack.size()); // Parse the property key. ExpectNext(JsonToken::STRING); property_stack.emplace_back(ScanJsonPropertyKey(&cont)); ExpectNext(JsonToken::COLON); // Continue to start producing the first property value. continue; } case JsonToken::LBRACK: Consume(JsonToken::LBRACK); if (Check(JsonToken::RBRACK)) { value = factory()->NewJSArray(0, PACKED_SMI_ELEMENTS); break; } // Start parsing an array with elements. cont_stack.emplace_back(std::move(cont)); cont = JsonContinuation(isolate_, JsonContinuation::kArrayElement, element_stack.size()); // Continue to start producing the first array element. continue; case JsonToken::TRUE_LITERAL: ScanLiteral("true"); value = factory()->true_value(); break; case JsonToken::FALSE_LITERAL: ScanLiteral("false"); value = factory()->false_value(); break; case JsonToken::NULL_LITERAL: ScanLiteral("null"); value = factory()->null_value(); break; case JsonToken::COLON: case JsonToken::COMMA: case JsonToken::ILLEGAL: case JsonToken::RBRACE: case JsonToken::RBRACK: case JsonToken::EOS: ReportUnexpectedCharacter(CurrentCharacter()); // Pop the continuation stack to correctly tear down handle scopes. while (!cont_stack.empty()) { cont = std::move(cont_stack.back()); cont_stack.pop_back(); } return MaybeHandle<Object>(); case JsonToken::WHITESPACE: UNREACHABLE(); }
- JsonToken::NUMBER 的处理函数是 ParseJsonNumber();
- 处理字符串时对 . e 单独处理
- 处理 e 时下一个字符如果是 - + 就忽略
if (CurrentCharacter() == '.') { uc32 c = NextCharacter(); if (!IsDecimalDigit(c)) { AllowHeapAllocation allow_before_exception; ReportUnexpectedCharacter(c); return handle(Smi::FromInt(0), isolate_); } AdvanceToNonDecimal(); } if (AsciiAlphaToLower(CurrentCharacter()) == 'e') { uc32 c = NextCharacter(); if (c == '-' || c == '+') c = NextCharacter(); if (!IsDecimalDigit(c)) { AllowHeapAllocation allow_before_exception; ReportUnexpectedCharacter(c); return handle(Smi::FromInt(0), isolate_); } AdvanceToNonDecimal(); }
- 处理字符串时对 . e 单独处理
-
思考题:
- 以下语句的输出结果
-
- JSON.parse(’-1111’);
-
- JSON.parse(‘11111’);
-
- JSON.parse(‘1.111’);
-
- JSON.parse(‘1111e1’);
-
- JSON.parse(‘1111e+1’);
-
- JSON.parse(‘1111e-1’);
-
- 以下语句的输出结果
1 回复
通常的使用场景是 JSON.parse(’“2382E2”’) ~