by Khoa Pham
通過Khoa Pham
了解React Native中的不同JavaScript環境 (Get to know different JavaScript environments in React Native)
React Native can be very easy to get started with, and then at some point problems occur and we need to dive deep into it.
React Native可能很容易上手 ,然后在某些時候出現問題,我們需要深入研究它。
The other day we had a strange bug that was only occurring in production build, and in iOS only. A long backtrace in the app revealed that it was due to Date
constructor failure.
前幾天,我們遇到了一個奇怪的錯誤,該錯誤僅在生產版本中發生,并且僅在iOS中發生。 應用程序中的長時間回溯顯示這是由于Date
構造函數故障引起的。
const date = new Date("2019-01-18 12:00:00")
This returns the correct Date
object in debug mode, but yields Invalid Date
in release. What’s special about Date
constructor? Here I’m using react native 0.57.5 and no Date
libraries.
這會在調試模式下返回正確的Date
對象,但在發行版中會產生Invalid Date
。 Date
構造函數有何特別之處? 在這里,我使用的是react native 0.57.5,并且沒有Date
庫。
日期構造器 (Date constructor)
The best resource for learning Javascript is via Mozilla web docs, and entering Date:
學習Javascript的最佳資源是通過Mozilla Web文檔,然后輸入Date :
Creates a JavaScript
Date
instance that represents a single moment in time.Date
objects use a Unix Time Stamp, an integer value that is the number of milliseconds since 1 January 1970 UTC.創建一個表示單個時刻JavaScript
Date
實例。Date
對象使用Unix時間戳記 ,它是一個整數值,它是自1970年1月1日UTC以來的毫秒數。
Pay attention to how Date can be constructed by dateString:
注意如何用dateString構造Date:
dateString
String value representing a date. The string should be in a format recognized by theDate.parse()
method (IETF-compliant RFC 2822 timestamps and also a version of ISO8601).
dateString
表示日期的字符串值。 該字符串應采用Date.parse()
方法可識別的格式( 符合IETF的RFC 2822時間戳以及ISO8601的版本 )。
So Date
constructor uses static method Date.parse
under the hood. This has very specific requirement about the format of date string that it supports
所以Date
構造Date.parse
在Date.parse
使用靜態方法Date.parse
。 這對它支持的日期字符串的格式有非常具體的要求
The standard string representation of a date time string is a simplification of the ISO 8601 calendar date extended format (see Date Time String Format section in the ECMAScript specification for more details). For example,
"2011-10-10"
(date-only form),"2011-10-10T14:48:00"
(date-time form), or"2011-10-10T14:48:00.000+09:00"
(date-time form with milliseconds and time zone) can be passed and will be parsed. When the time zone offset is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as local time.日期時間字符串的標準字符串表示形式是ISO 8601日歷日期擴展格式的簡化形式(有關更多詳細信息,請參見ECMAScript規范中的“ 日期時間字符串格式”部分)。 例如,
"2011-10-10"
(僅日期格式),"2011-10-10T14:48:00"
(日期時間格式)或"2011-10-10T14:48:00.000+09:00"
(具有毫秒和時區的日期時間格式)可以傳遞并進行解析。 缺少時區偏移時,僅日期格式將解釋為UTC時間,而日期時間格式將解釋為本地時間。
The ECMAScript specification states: If the String does not conform to the standard format the function may fall back to any implementation–specific heuristics or implementation–specific parsing algorithm. Unrecognizable strings or dates containing illegal element values in ISO formatted strings shall cause
Date.parse()
to returnNaN
.ECMAScript規范指出:如果String不符合標準格式,則該函數可能會退回到任何特定于實現的試探法或特定于實現的解析算法。 ISO格式的字符串中無法識別的字符串或包含非法元素值的日期將導致
Date.parse()
返回NaN
。
The reason that we get Invalid Date in iOS must be because the code was run in two different JavaScript environments and they somehow have different implementation of the Date parsing function.
我們在iOS中獲得無效日期的原因一定是因為代碼是在兩個不同JavaScript環境中運行的,并且它們在某種程度上對日期解析功能具有不同的實現。
JavaScript環境 (JavaScript Environment)
React Native guide has a dedicated section about JavaScript environments.
React Native指南專門介紹了JavaScript環境 。
When using React Native, you’re going to be running your JavaScript code in two environments:
使用React Native時,您將在兩種環境中運行JavaScript代碼:
In most cases, React Native will use JavaScriptCore, the JavaScript engine that powers Safari. Note that on iOS, JavaScriptCore does not use JIT due to the absence of writable executable memory in iOS apps.
在大多數情況下,React Native將使用JavaScriptCore (支持SafariJavaScript引擎)。 請注意,在iOS上,由于iOS應用程序中沒有可寫的可執行內存,因此JavaScriptCore不使用JIT。
When using Chrome debugging, all JavaScript code runs within Chrome itself, communicating with native code via WebSockets. Chrome uses V8 as its JavaScript engine.
使用Chrome調試時,所有JavaScript代碼都在Chrome本身中運行,并通過WebSockets與本機代碼進行通信。 Chrome使用V8作為其JavaScript引擎。
While both environments are very similar, you may end up hitting some inconsistencies. We’re likely going to experiment with other JavaScript engines in the future, so it’s best to avoid relying on specifics of any runtime.
盡管兩種環境非常相似,但您最終可能會遇到一些不一致之處。 將來我們可能會嘗試使用其他JavaScript引擎,因此最好避免依賴任何運行時的細節。
React Native also uses Babel and some polyfills to have some nice syntax transformers, so some of the code that we write may not be necessarily supported natively by JavascriptCore
.
React Native還使用Babel和某些polyfill來具有一些不錯的語法轉換器,因此JavascriptCore
不一定必須支持我們編寫的某些代碼。
Now it is clear that while we debug our app via Chrome debugger, it works because V8 engine handles that. Now try turning off Remote JS Debugging: we can see that the above Date constructor fails, which means it is using JavascriptCore
.
現在很明顯,當我們通過Chrome調試器調試應用程序時,它可以工作,因為V8引擎可以處理它。 現在嘗試關閉遠程JS調試:我們可以看到上面的Date構造函數失敗,這意味著它正在使用JavascriptCore
。
To confirm this issue, let’s run our app in Xcode and go to the Safari app on MacOS to enter Development menu. Select the active Simulator and choose JSContext on the current iOS app. Remember to turn off Remote JS Debugging so that the app uses JavascriptCore:
為確認此問題,讓我們在Xcode中運行我們的應用程序,然后轉到MacOS上的Safari應用程序以進入“開發”菜單。 選擇活動的Simulator,然后在當前iOS應用上選擇JSContext。 請記住關閉遠程JS調試,以便該應用程序使用JavascriptCore:
Now open the Console in Safari dev tools, and we should have access to JavascriptCore inside our app. Try running the above Date
constructor to confirm that it fails:
現在,在Safari開發工具中打開控制臺,我們應該可以在應用程序內訪問JavascriptCore。 嘗試運行上面的Date
構造函數以確認它失敗:
有效日期字符串格式是什么? (What are legit date string formats?)
Since 2016, JavascriptCore supports most ES6 features:
自2016年以來, JavascriptCore支持大多數ES6功能:
As of r202125, JavaScriptCore supports all of the new features in the ECMAScript 6 (ES6) language specification
從r202125開始 ,JavaScriptCore支持ECMAScript 6(ES6)語言規范中的所有新功能。
And it was fully confirmed a year later in JSC ? ES6
一年后,它在JSC中得到了充分證實? ES6
ES2015 (also known as ES6), the version of the JavaScript specification ratified in 2015, is a huge improvement to the language’s expressive power thanks to features like classes, for-of, destructuring, spread, tail calls, and much more
ES2015 (也稱為ES6),在2015年批準了JavaScript規范的版本,是一個巨大的進步了語言的表達能力歸功于像功能類 , 換的 , 解構 , 傳播 , 尾調用和更
WebKit’s JavaScript implementation, called JSC (JavaScriptCore), implements all of ES6
WebKitJavaScript實現(稱為JSC(JavaScriptCore)) 實現了所有ES6
For more details about JavaScript features supported by different JavaScript engines, visit this ECMAScript comparison table.
有關不同JavaScript引擎支持JavaScript功能的更多詳細信息,請訪問此ECMAScript比較表 。
Now for the date string format, from Date.parse, let’s visit ECMAScript 2015 specification to see what it says about date string format:
現在,從Date.parse中獲取日期字符串格式,讓我們訪問ECMAScript 2015規范,以了解日期字符串格式的含義:
ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
ECMAScript基于ISO 8601擴展格式的簡化,為日期時間定義了字符串交換格式。 格式如下: YYYY-MM-DDTHH:mm:ss.sss Z
Where the fields are as follows:
字段如下:
"T"
appears literally in the string, to indicate the beginning of the time element.
"T"
字面上出現在字符串中,以指示時間元素的開始。
So JavascriptCore
requires T
specifier and V8 can work without it. The fix for now is to always include that T specifier. This way we always follow ECMAScript standards to make sure it works across different JavaScript environments.
因此, JavascriptCore
需要T
說明符,而V8可以不使用它。 現在的解決方法是始終包含該T指定符。 這樣,我們始終遵循ECMAScript標準,以確保其可在不同JavaScript環境中正常工作。
const date = new Date("2019-01-18 12:00:00".replace(' ', 'T'))
And now it returns correct Date
object. There may be difference between JavascriptCore on iOS and macOS, and among different iOS versions. The lesson learned here is that we should always test our app thoroughly in production and on devices to make sure it works as expected.
現在,它返回正確的Date
對象。 iOS和macOS上的JavascriptCore之間以及不同的iOS版本之間可能存在差異。 從這里吸取的教訓是,我們應該始終在生產環境和設備上全面測試我們的應用程序,以確保其能夠按預期運行。
翻譯自: https://www.freecodecamp.org/news/get-to-know-different-javascript-environments-in-react-native-4951c15d61f5/