Giter VIP home page Giter VIP logo

rockonyu.github.io's Issues

我應該用 for 迴圈取代所有 array.prototype.forEach 嗎?

最近收到了一些建議:不要直接使用 array 的 forEachmap 的 API,理由是效能不佳與相容舊版瀏覽器,建議調整的做法是透過 underscore 或是 lodash 等第三方套件的 eachmap 遍歷陣列。

在網路上搜尋了一些文章,真的發現有類似的說法,該篇文章指出使用 forEach 甚至比單純的 for 迴圈慢上了 95% 😱。

這讓我覺得有些好奇瀏覽器原生實作的 API 為什麼會比第三方套件慢上許多,理論上應該各間廠商都會盡量優化這類處理資料的 API 才是。

在閱讀 underscore 原始碼後發現了一些蹊蹺,其實作方式就是改用 for 迴圈來遍歷陣列,因此問題逐漸明朗,並非第三方實作的比較快,而是普遍認為操作陣列透過 for 會相對 array.prototype.forEach 快上許多。

因此我透過 https://jsben.ch 測試了兩者的差異,在 mac 電腦的 chrome 跑出以下成績:

2019-02-27 10 53 13

畢竟 for 迴圈也是瀏覽器原生的 API,兩者相較起來速度提升約 50%,其中最快的 for (cache length) 會在執行前將陣列的長度一併存到區域變數,實作方式大約如下:

for(let i = 0, len = array.length; i < len; i++) { ... }

將將!以後大家請愛用 for 迴圈......嗎!?

在回家的路上順手用 iPhone 的 safari 重新跑了測試,卻發現完全不同的結果:

image from ios

在 iPhone 的 array.prototype.forEach 將近比 for 快上 75% 啊!

真的應該用 for 迴圈取代所有 array 的輪詢操作嗎?以下是我個人的看法:

  1. 針對陣列的操作直接使用原生的 forEachmap:理由是這兩者效能的差異是偽議題,我認為除非超巨量資料處理,兩者間的差距可以忽略,反過來說全部使用 for 也不會讓你的應用程式效能提升一個檔次,使用 array 的 API 能夠讓邏輯處理的意圖更加明顯。
  2. 不同瀏覽器間的差異已經明顯減少,但仍然存在,因此應該避免刻意優化特定瀏覽器的作法。
  3. 你可能不需要 Lodash/Underscore:這兩個是功能完善的工具庫,但我認為尋常的操作應該盡量使用原生 API 解決。

angular-translate 套件的後置處理 (postProcess)

angular-translate 是一套 angularJS 處理多語系的套件,功能大致上是頁面上不直接寫文字,改透過 KEY 去換取當前語系的字樣。

最近有個需求是要取得當前頁面用到哪些 KEY,原本在查要如何監測 translateChangeSuccess 事件,查到後來發現套件本身就提供了一個很方便的功能,叫做 postProcess (後處理)。

使用方式也很簡單,在 angular-translate 的設定檔同時設定:

$translateProvider.postProcess(
  (
    translationId,
    translation,
    interpolatedTranslation,
    params,
    lang
  ) => {
    console.log(translation);
    return '<span style="color: #cccccc">' + translationId + '(' + lang + '):</span> ' +
      (interpolatedTranslation ? interpolatedTranslation : translation);
  }
)

簡單紀錄各參數代表的意義:
translationId 頁面使用的多語系 KEY
translation 透過 KEY 取得當前多語系的字串
interpolatedTranslation 透過 KEY 取得當前多語系的字串 (包含 params)
params 多語系字串間插入的參數
lang 這個沒特別看,字面上意思應該是當前語系 XD?

其餘部分可以參考 JSBin

angularJS 在地化幣別與日期的設定方式

angularJS 本身針對在地化提供很漂亮的設定方式 (裝飾者模式?),簡單 google 後查到兩種做法。

  1. 直接在頁面上載入在地化的 script
  2. 設定在應用程式的 config (內容與上述方式差不多)

我們公司因為希望幣別格式由後端控制,因此選擇第二種做法:

angular
  .module('myApp')
  .config(['$provide', ($provide) => {
    $provide.decorator('$locale', ['$delegate', function ($delegate) {
      $delegate.DATETIME_FORMATS.medium = "yyyy/MM/dd HH:mm";
      $delegate.DATETIME_FORMATS.mediumDate = "yyyy/MM/dd";
      $delegate.DATETIME_FORMATS.mediumTime = "HH:mm";
    
      $delegate.NUMBER_FORMATS.CURRENCY_SYM = "$";
      $delegate.NUMBER_FORMATS.PATTERNS[1].maxFrac = 0;
      $delegate.NUMBER_FORMATS.PATTERNS[1].posPre = '\u00A4';
      $delegate.NUMBER_FORMATS.PATTERNS[1].negPre = '-\u00A4';
      $delegate.NUMBER_FORMATS.PATTERNS[1].negSuf = '';
      return $delegate;
    }]);
  }]
);

這是完整的範例可以參考:
https://jsbin.com/hulaxewuli/edit?html,output

在 AngularJS 專案套用 React 元件的方式

簡單的範例演示如何在 AngularJS 專案使用 ReactJS 元件

我只用了 presentational component,
因為如果 React 跟 AngularJS 各自管理 state 會有點太複雜。

網路上還有很多其他的輪子寫得更好,例如 react2angular
但我想用簡單的範例 (ng 官網 TodoApp) 驗證在某些情境,不需要那麼大的輪子。

React 與 AngularJS 之間會是 driectives 透過溝通:
https://jsbin.com/cezapuvaga/1/edit?html,js,output

整理上半年分享的簡報

curry 化

參考自:https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch4.html

curry 的概念:傳遞一部分的參數給函數,並返回另一個函數去處理剩下的參數

var add = x => y => x + y;
var increment = add(1);

以下是原文提供 curryify 的 函數,也可以從 lodash-fp 套件裡取得。

var curry = require('lodash').curry;

var match = curry(function(what, str) {
  return str.match(what);
});

var replace = curry(function(what, replacement, str) {
  return str.replace(what, replacement);
});

var filter = curry(function(f, ary) {
  return ary.filter(f);
});

var map = curry(function(f, ary) {
  return ary.map(f);
});

一個簡單但非常重要的模式:策略性把要操作的數據放到最後參數

map 包裹參數是單個元素的函數,就能把它轉換為參數為陣列的函數。

var getChildren = function(x) {
  return x.childNodes;
};

var allTheChildren = map(getChildren);
// allTheChildren([..., ...])

通常也不定義操作陣列的函數,因為用 curryify 的 map 包裹即可得到結果。

Google 社群前端筆記:PWA

Progressive Web Apps 旨在提供更好的網頁瀏覽體驗。

PWA 可以直接加入手機桌面、相對於 Native App 容量非常的小,在 android 上是直接安裝一個 apk 到手機並原生開啟 (不透過 chrome 瀏覽器 app)。

Twitter 約 80% 用戶透過 mobile 裝置瀏覽網頁,並聲稱支援 PWA 後增加了 65% 頁面 session 瀏覽量。

PWA 是跨瀏覽器的協議,並非只有 chrome 瀏覽器支援。

Manifest Generator 可以生成網站中繼檔以部分支援 PWA ,例如加入手機桌面的功能。

不同瀏覽器要 Push 通知給用戶差異很大,講者建議透過 Firebase cloud messaging in JavaScript 實踐。

http://bit.ly/pwa-media 用這個網站體驗 PWA 與媒體互動 (目前 android 限定)

瀏覽器的 navigator.share API 會喚起手機 Native 的分享對話框。

檢查網站對 PWA 的支援度:

  1. 連到 Lighthouse 敲入網址
  2. Chrome 開發者工具的 audits 同樣可以得到來自 lighthouse 的評分

講者分享了 workboxjs 提供對離線網站的支援,可以簡單的將資源緩存在本地。

網站的簡介:

「Workbox is a set of service worker libraries that making build progressive web apps easy.」

AMP Roadshow Taipei 參加筆記

AMP  是為了加速行動裝置的網頁載入速度,以提升使用者體驗而生的專案。

網頁需要改用 AMP-HTML 語法,以獲得 AMP 加速網頁顯示。

讀取速度低落多數原因跟 JS、CSS 與圖片有關,介紹了 AMP 的解決方案:

  1. AMP 網頁不能自訂 JavaScript,需要透過 AMP 元件
  2. 外部 CSS 需要直接放到該頁面。
  3. 圖片改用 標籤並要先定義好寬高

在世界各地都有 AMP 的 Server 以提高在世界各地的連線速度,點進 AMP 網頁會連到一個 google 預先載入的網頁 (由 google host 的站台)。

錯誤的迷思:

  1. AMP 頁面都被快取住,不能有動態內容 => 可以透過 API 更新
  2. 原始頁面更新後很難同步更新到快取住的 AMP 網頁 => 當有用戶點了最新內容或是開發者可以透過 API 主動更新 AMP 網頁
  3. AMP 會偷走你的流量 => AMP 支援超過 40 家公司的追蹤碼,使用 AMP 元件再將流量導回自己網頁
  4. 實作 AMP 並不會直接提高 Google 搜尋的排名 => 但有可能因為瀏覽人數變多而提升排名

大絕招:將某些尚未有 AMP 元件的功能放入網頁,可以使用 ,例如 google map 或某些第三方的追蹤碼等等。

的限制:https only、不可用於顯示廣告

實作了 AMP 後,行動版 google 搜尋結果的名稱旁邊會出現閃電符號,代表該頁面支援 AMP 網頁。

介紹了兩個工具:

  1. AMP Validator:檢查網頁是否符合 AMP 規範
  2. AMP by Example:包含元件的介紹與範例

如何開始實作 AMP:

  1. 查看 GA,選定一個從 Google Search 導入較多瀏覽的頁面 (不要全改)
  2. 以 AMP by Example 的專案程式碼為基礎,把上述頁面的靜態部分改用 AMP HTML 搭建起來
  3. 使用 與 實作較複雜的功能 (需要 javascript 的部分) 及加入追蹤碼

Yahoo 拍賣宣稱實作 AMP 頁面後,跳出率降了三成,交易量上升三成。

個人感想:不能用 JavaScript 晴天霹靂,但實作 AMP 的店家比想像中還多很多,提供一些關鍵字,讓大家在「行動裝置」透過 google 搜尋試試看 AMP 的威力。

Google 關鍵字:「nintendo switch yahoo」、「戴資穎」

純函數的好處

參考自:https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch3.html

純函數代表相同的輸入,永遠會得到相同的輸出,而且沒有任何可被觀察到的副作用。

這是兩個陣列函數在 MDN 上的說明:
Array.prototype.slice() 方法會回傳一個新陣列物件,為原陣列選擇之 begin 至 end(不含 end)部分的淺拷貝(shallow copy),而原本的陣列將不會被修改。

Array.prototype.splice() 方法可以藉由刪除既有元素並/或加入新元素來改變一個陣列的內容。

函數編程討厭會異動原本變數內容的方法,比較偏好使用前者 slice

關於副作用

概觀來講,只要是跟函數外部環境發生的交互就都是副作用。

純函數的好處

  1. 可以透過 _.memoize 等方式緩存
  2. 因為沒有受到外部環境干擾,函數本身容易被移植
  3. 容易被測試
  4. 引用透明:一段代碼可以替換成它執行所得的結果
  5. 並行代碼:純函數不需要訪問共享的系統狀態

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.