2020年6月9日 星期二

《面試官別再問》JavaScript 動態變數怎麼寫,動態呼叫function函式

JavaScript 動態呼叫函式:讓程式碼活起來的實用技!

各位朋友,大家好!上次我們聊了聊 JavaScript 裡怎麼「動態建立變數」,也就是把變數名稱當成物件屬性來用。今天,我們要更進一步,來談談怎麼「動態呼叫函式」。

什麼是動態呼叫函式呢?簡單來說,就是我們不直接寫死要呼叫哪個函式,而是透過一個變數或字串,來決定現在要執行哪一個函式。這在開發一些比較彈性、或者需要根據不同條件執行不同動作的系統時,非常管用。


最推薦:把函式也當成物件的「屬性」來存!

就像上次談到動態變數一樣,最安全、最推薦的方法,就是把您的函式們,也通通整理到一個物件裡面。這樣一來,要動態呼叫哪個函式,就跟動態取得物件屬性一樣簡單。

假設我們正在開發一個訂單處理系統,根據不同的訂單狀態,需要執行不同的處理動作:

JavaScript
// 建立一個物件,專門用來存放各種處理函式
const orderProcessors = {
  // 函式一:處理「待付款」的訂單
  handlePending: function(orderId) {
    console.log(`處理訂單 ${orderId}: 提醒客戶盡快付款...`);
    // 這裡可以寫寄送付款通知、檢查付款狀態等邏輯
  },

  // 函式二:處理「已付款」的訂單
  handlePaid: function(orderId) {
    console.log(`處理訂單 ${orderId}: 準備出貨!`);
    // 這裡可以寫更新庫存、生成出貨單等邏輯
  },

  // 函式三:處理「已取消」的訂單
  handleCancelled: function(orderId) {
    console.log(`處理訂單 ${orderId}: 訂單已取消,通知相關部門。`);
    // 這裡可以寫恢復庫存、發送取消通知等邏輯
  }
};

// 假設這是一個從資料庫或使用者操作拿到的訂單狀態
const currentOrderStatus = "Paid"; // 可能是 "Pending", "Paid", "Cancelled"
const currentOrderId = "ORD-20250719-001";

// 現在,我們要根據 currentOrderStatus 動態呼叫對應的函式
// 怎麼辦到呢?就是利用中括號來取物件屬性!
const handlerFunctionName = `handle${currentOrderStatus}`; // 組合出函式名稱字串 "handlePaid"

// 檢查一下這個函式是否存在,比較保險
if (typeof orderProcessors[handlerFunctionName] === 'function') {
  // 動態呼叫函式!
  orderProcessors[handlerFunctionName](currentOrderId);
  // 如果 currentOrderStatus 是 "Paid",就會執行 handlePaid(currentOrderId)
} else {
  console.log(`找不到處理 ${currentOrderStatus} 狀態的函式。`);
}

// 輸出: 處理訂單 ORD-20250719-001: 準備出貨!

這種做法的優點跟上次說的動態變數很像:

  • 集中管理:所有的相關函式都收納在一個物件裡,程式碼整齊好閱讀。

  • 彈性擴充:以後要新增一種訂單狀態的處理?直接在 orderProcessors 裡加一個新函式就好,不用改動到太多地方。

  • 安全可靠:不會有資安風險,也不會影響效能。

  • 容易除錯:函式都在那邊,哪裡出錯一眼就能找到。


次選項:window 物件 (只在瀏覽器裡面用得到)

跟動態變數一樣,在瀏覽器環境下,如果您把函式宣告成全域的(或者用 function declaration 這種方式),那它也會掛到 window 物件底下。這時候,您也可以透過 window 物件來動態呼叫:

JavaScript
// 注意:這段程式碼只在瀏覽器環境下有效喔!
if (typeof window !== 'undefined') {
  // 宣告一個全域函式
  function sayHello(name) {
    console.log(`哈囉,${name}!很高興見到你!`);
  }

  const funcName = "sayHello";
  const userName = "小明";

  // 檢查一下這個函式是否存在
  if (typeof window[funcName] === 'function') {
    // 動態呼叫全域函式
    window[funcName](userName);
  } else {
    console.log(`找不到函式 ${funcName}。`);
  }
  // 輸出: 哈囉,小明!很高興見到你!
}

這個方法的限制一樣:只適用於瀏覽器環境,而且會增加全域變數和函式的數量,讓您的全域環境變得比較混亂。除非有很特殊的理由,否則還是建議用物件來管理。


千萬要小心:eval() 函數 (絕對不推薦!)

又見到我們的老朋友 eval() 了!理論上,它也可以用來動態呼叫函式:

JavaScript
function greetSomeone(name) {
  console.log(`很高興見到你,${name}!`);
}

const funcToCall = "greetSomeone";
const personName = "陳先生";

// 千萬小心!這行程式碼非常危險!
eval(`${funcToCall}('${personName}')`); // 動態建立並執行字串 "greetSomeone('陳先生')"

// 輸出: 很高興見到你,陳先生!

但就像我們上次說的,eval() 根本就是一個「不定時炸彈」。它的缺點實在太多,包括:

  • 嚴重的資安風險:這是最致命的一點。只要有心人士在您傳給 eval() 的字串裡動手腳,您的網站或系統就可能被控制。

  • 效能問題:執行速度慢,不適合用在需要高效能的地方。

  • 除錯困難:您會很難找到問題出在哪裡。

  • 作用域混亂:可能導致難以預料的行為。

所以,再次強調,為了您程式碼的安全、穩定與可維護性,請務必避免使用 eval() 來動態呼叫函式


結語:物件導向的智慧,讓程式碼更靈活!

JavaScript 在設計上,就是一個非常靈活的語言。當您需要「動態」地去做某些事情時,不管是變數還是函式,最安全、最有效率、也最符合現代 JavaScript 開發模式的做法,就是善用「物件」

把相關的變數和函式組織在物件裡,您就能像操作檔案夾一樣,輕鬆地根據名稱去存取或執行它們。這樣不僅讓您的程式碼更整潔、更易於管理,也大大提升了程式的彈性與可擴充性。

希望這次的分享,能幫助大家在撰寫 JavaScript 時,能更得心應手,寫出既靈活又穩固的程式碼。如果您有其他更棒的方法,或者有任何疑問,都歡迎留言,大家一起交流!

2020年5月11日 星期一

vue面試題vue-cli相關知識點

沒有框架的日子
先回想一下在沒有框架的時候,開發者的日常會長什麼樣子吧。

那時最流行的「套件」非 jQuery 莫屬了,語法簡潔、直覺好用的元素選取器,語法便捷的事件監聽註冊,豐富的開發者生態系產出大量的開源套件,以及最重要的,弭平瀏覽器 XHR 差異的 ajax 函式,將複雜的瀏覽器差異藏在套件中,讓開發者只需要專注在想實作的邏輯即可。

透過好用的元素選取器及事件監聽,開發者們可以依據使用者的行為,靈活操作 DOM 元素的結構及樣式,jQuery 的這些特色直到 2019 的現在,都仍是很實用的功能,甚至 程式碼本身 也有許多值得開發者學習的地方;但隨著專案規模逐漸增大,程式複雜度不斷上升,直接操作 DOM 的缺點也就逐漸浮出檯面:

難以維護
HTML、CSS、JavaScript 無法維持原先的各司其職,因為需要透過 JavaScript 處理互動內容,勢必要將結構、樣式寫到 JavaScript 的部份中,也就因此造成架構耦合度提高,程式碼管理困難。

效能低落
在 Reflow 及 Repaint 是什麼? 中有提到 Render Tree 的概念,當 DOM 被改變,勢必要觸發整個 Reflow & Repaint 的流程,頻繁的改動觸發重複渲染,便會讓頁面效能被消耗殆盡。

框架的功能

既然有前述的問題,自然會有強者試圖解決它。歷史進程中有許多大神拋出了方法論,或是實作出解決方案,但這中間的歷史礙於篇幅,就容筆者簡略帶過吧。總之,現今的「框架」其實就是一種提升開發效率、降低維護難度的開發架構。主流的框架如 React、Vue 等,大都擁有這些特性:

問題一:構建的vue-cli 工程都到了哪些技術,它們的作用分別是什麼?

1、vue.js:vue-cli工程的核心,主要特點是 雙向數據綁定 和 組件系統。
2、vue-router:vue官方推薦使用的路由框架。
3、vuex:專為 Vue.js 應用項目開發的狀態管理器,主要用於維護vue組件間共用的一些 變量 和 方法。
4、axios( 或者 fetch 、ajax ):用於發起 GET 、或 POST 等 http請求,基於 Promise 設計。
5、webpack:模塊加載和vue-cli工程打包器。


問題二:vue-cli 工程常用的npm 命令有哪些?

下載 node_modules 資源包的命令:
npm install

啟動 vue-cli 開發環境的 npm命令:
npm run dev

vue-cli 生成 生產環境部署資源 的 npm命令:
npm run build

用於查看 vue-cli 生產環境部署資源文件大小的 npm命令:
npm run build --report

問題三:請說出vue-cli工程中每個文件夾和文件的用處

build 文件夾:用於存放 webpack 相關配置和腳本。開發中僅 偶爾使用 到此文件夾下 webpack.base.conf.js 用於配置 less、sass等css預編譯庫,或者配置一下 UI 庫。
config 文件夾:主要存放配置文件,用於區分開發環境、線上環境的不同。
常用到此文件夾下 config.js 配置開發環境的 端口號、是否開啟熱加載 或者 設置生產環境的靜態資源相對路徑、是否開啟gzip壓縮、npm run build 命令打包生成靜態資源的名稱和路徑等。
dist 文件夾:默認 npm run build 命令打包生成的靜態資源文件,用於生產部署。
node_modules:存放npm命令下載的開發環境和生產環境的依賴包。
src: 存放項目源碼及需要引用的資源文件。
src下assets:存放項目中需要用到的資源文件,css、js、images等。
src下componets:存放vue開發中一些公共組件:header.vue、footer.vue等。
src下emit:自己配置的vue集中式事件管理機制。
src下router:vue-router vue路由的配置文件。
src下service:自己配置的vue請求後台接口方法。
src下page:存在vue頁面組件的文件夾。
src下util:存放vue開發過程中一些公共的.js方法。
src下vuex:存放 vuex 為vue專門開發的狀態管理器。
src下app.vue:使用標籤<route-view></router-view>渲染整個工程的.vue組件。
src下main.js:vue-cli工程的入口文件。
index.html:設置項目的一些meta頭信息和提供<div id="app"></div>用於掛載 vue 節點。
package.json:用於 node_modules資源部 和 啟動、打包項目的 npm 命令管理。

問題四. 什麼是 MVVM?

MVVM 是 Model-View-ViewModel 的縮寫,MVVM 是一種設計思想。 Model 層代表數據模式,也可以在 Model 中定義數據修改和操作的業務邏輯;View 代表 UI 組件,它負責將數據模型轉化爲 UI 展現出來,ViewModel 是一個同步 View 和 Model 的對象。

問題五. 父組件向子組件傳值的方法?

父組件傳遞的數據子組件用 props 方法接收。

子組件通過兩種方式接收:可以傳遞任何類型(數組,對象,各種數據類型等等)

*props:[‘title’,‘likes’,‘isPublished’,‘author’];

*props:{title:String,likes:Number}

詳細介紹看這篇:Vue 父組件向子組件傳值

https://blog.csdn.net/qq_34928693/article/details/80539350

問題六. 子組件向父組件傳值的方法?

子組件向父組件傳值用this.$emit(key,value) ,父組件接收的時候需要在父組件中創建的子組件的標籤中綁定Key,格式:@Key=“方法名”,父組件聲明這個方法,方法帶參數,這個參數就是子組件傳遞的Value。

詳細介紹看這篇:Vue 子組件向父組件傳值

https://blog.csdn.net/sisi_chen/article/details/81635216

問題七. Vuex 是什麼?哪種功能場景使用它?

Vuex 是專門爲 Vue.js 設計的狀態管理模式,它採用集中式儲存管理 Vue 應用中所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

當項目龐大的時候使用它:

*需要動態的註冊響應式數據;

*需要命名空間 namespace 來管理組織我們的數據;

*希望通過插件,來更改記錄;方便測試;以上這些需要和希望,都是我們 vuex 需要做的一些事情。

問題八. Vuex 有哪幾種屬性?

*state:基本數據

*getters:從基本數據派生的數據

*mutations:提交更改數據的方法,同步!

*actions:像一個裝飾器,包裹 mutations,使之可以異步。

*modules:模塊化 Vuex。

6. 如何讓 CSS 旨在當前組件中起作用?

當前組件的 < style> 標籤修改爲 < style scoped>

問題九.生命週期是什麼
Vue 實例有一個完整的生命週期,也就是從開始創建、初始化數據、編譯模版、掛載Dom -> 渲染、更新-> 渲染、卸載等一系列過程,我們稱這是Vue的生命週期。

各個生命週期的作用

生命週期描述
beforeCreate組件實例被創建之初,組件的屬性生效之前
created組件實例已經完全創建,屬性也綁定,但真實dom還沒有生成,$el還不可用
beforeMount在掛載開始之前被調用:相關的render 函數首次被調用
mountedel 被新創建的vm.$el 替換,並掛載到實例上去之後調用該鉤子
beforeUpdate組件數據更新之前調用,發生在虛擬DOM 打補丁之前
update組件數據更新之後
activitedkeep-alive專屬,組件被激活時調用
deadctivatedkeep-alive專屬,組件被銷毀時調用
beforeDestory組件銷毀前調用
destoryed組件銷毀後調用

當工程師的價值不再只是寫 Code,公司還看得見你的貢獻嗎?

 最近跟 AI、軟體開發流程轉變相關的討論越來越多。 很多人關注的是: AI 會不會取代工程師? 未來還需不需要寫 Code? 工程師應該學什麼新技能? 但有一個更現實的問題,可能很多工程師每天都正在面對: 當你的工作價值不再只是「寫多少 Code」,公司是...