大家好,我是 Eric。
今天,我們要正式進入「程式語言」的領域。在此之前的 HTML,充其量只是語法,缺乏了語言的特性。要能稱得上語言,必須要具備發展出演算法,以及具備特定資料結構的能力。
程式 = 演算法 + 資料結構
在開始深入了解 WordPress 所使用的 JavaScript 之前,我們需要先熟悉一下開發人員工具的環境。開發人員工具的模擬器 (Console) 面板,對於自己在測試各種功能與下方的範例時很有幫助。
接著,我們需要先對程式語言中的變數 (variables) 與函式(functions) 有一些基礎概念。
變數的目的,在於指派特定記憶體空間給某些資料,供後續運算使用。
在 JavaScript 中,我們可以透過 var
這個方法來定義變數。
var variable = "this is a variable";
在 ES6 以後,除了 var
以外,也可以透過 let
的方式定義變數,可以避免因為函式範圍 (scope) 導致變數互相干擾的狀況。
一般而言,我們在建立變數時,會包含表達意涵的運算式 (expression) 與指派陳述式 (assignment statement)。前者的功能在「表意」,透過運算子、函式等方式,得出一個最終的數值 (結果);後者則是賦予變數運算的結果。
var name = "Eric"; //這是一個指派陳述式
name + " Chuang"; //這是一個運算式
var fullName = name + " Chuang"; //這是一個指派陳述式
所謂的型別,代表的是變數與生俱來的特性,會影響變數與其他變數的運算關係。例如兩個字串 (string) 相加 "Eric" + " Chuang"
的結果會是 Eric Chuang
,而兩個數字 (number) 相加 1 + 3
的結果會是 4
。
JavaScript 是一種弱型別的語言,意思是它在定義變數的過程中,並不需要指定型別,端看接下來如何運算。舉例來說:
var num = 1; //預設是數字
var num2 = 2; //預設是數字
var str = "me"; //預設是字串
num + num2 //會回傳 3,此時兩者的型別都是數字
num + str //會回傳字串 "1me",此時 num 在運算時,型別會被改為字串
型別 | 說明
-------+-------
undefined | 未定義,是一種特殊型別,與 0 或空值 (null
) 不相等。
boolean | 布林值,只有兩種結果:true
與 false
。
string | 字串。
number | 數字,可以進行四則運算。
object | 物件,可以賦予屬性與屬性值。例如:「筆」擁有「長度」、「顏色」兩種屬性,不同的筆,屬性值會不同。
運算子的功能在於建立運算式 (expression),運算式的功能包含計算、組合、判斷。常見的運算式可以分為下列幾種:
算數運算子 | 說明
-------+-------
+, -, *, / | 數字的四則運算。
% | 餘數。譬如 10%4
會回傳 2
。
+ | 字串相連。例如 "Eric" + " Chuang"
會回傳 "Eric Chuang"
。
比較運算子 | 說明
-------+-------
== | 比較前後值是否相等。會忽略型別,因此 "1"(字串) == 1(數字)
會回傳 true
。
=== | 比較前後值是否相等。會比較型別,所以 "1"(字串) == 1(數字)
會回傳 false
。
!= | 比較前後值是否「不」相等。會忽略型別,因此 "1"(字串) != 1(數字)
會回傳 false
。
!== | 比較前後值是否「不」相等。會比較型別,因此 "1"(字串) !== 1(數字)
會回傳 true
。
邏輯運算子 | 說明
-------+-------
&& | 如果前面可以轉換為 false,就回傳前面的運算式,否則回傳後面的運算式,例如 3 > 1 && 4 > 2
,因為 3 > 1
是 true
,因此會回傳 4 > 2
,也就是 true
;3 > 1 && 2 < 1
,因為 3 > 1
是 true
,因此回傳 2 < 1
,也就是 false
。
|| | 判斷前後條件是否有其中一項為 true
,有順序性,如果第一項為真,則不會繼續判斷後續條件。
! | 判斷後面條件是否為 false
。因此 !false
會回傳 true
,反之 !true
會回傳 false
。
隨著專案逐漸龐大,有時不同的開發人員會使用相同的命名方式。因此當代的網站開發引進了命名空間的概念,藉此定義自己的程式範圍,避免互相干擾。嚴格說來,JavaScript 並沒有內建的命名空間,但透過建立物件的方法,可以做出類似的效果。
我們從 Twenty Twenty 的 assets/js/index.js 中的第五行,看到命名空間的使用方式:
var twentytwenty = twentytwenty || {};
如果程式是一篇文章,那麼函式就是照樣造句,將複雜的運算,透過函式與參數的搭配,快速得到你要的結果。函式的基本語法如下:
function 函式名稱 ( 參數 ) {
/** 運算式 */
return 回傳值;
}
也可以這樣理解:
function test( a, b ){
return "同" + a + "同" + b;
}
test( "手", "腳" ); //回傳 "同手同腳"
我們在撰寫 JavaScript 的過程中,除了自行定義函式外,也會大量使用既有的函式,這裡列舉出幾種常用的函式。
函式名稱 | 說明
-------+-------
typeof(變數); | 檢驗變數的型別。
console.log(變數); | 將變數、或是函數回傳值顯示於開發人員工具的模擬器 (Console) 面板中。
Number(字串); | 將字串轉為數字,如果字串使用不同進位制,也會轉換。例如 Number("0x11");
會回傳 17 (16 進位制的 11 轉換為 10 進位值會變成 17)。
一般的函式,會透過 function 函式名稱
來宣告。但也可以透過以下方式來宣告函式:
var x = function(a, b) {return a * b};
var z = x[3, 4];
return z; //回傳 12
這種未經命名的函式,統稱為匿名函式。
除了上述的匿名函式外,另一種在 WordPress 相當實用的匿名函式,稱為立即函式 (self-invoking functions),其基本語法如下:
(function(參數){
/** 運算式 */
})();
我們在 Twenty Twenty 的 assets/js/customize.js 中可以看到相關的例子:
/* global wp, jQuery */
( function( $, api ) {
$( document ).ready( function() {
// Make it possible to reset the color based on a radio input's value.
// `active` can be either `custom` or `default`.
api.control( 'accent_hue_active' ).setting.bind( function( active ) {
var control = api.control( 'accent_hue' ); // Get the accent hue control.
if ( 'custom' === active ) {
// Activate the hue color picker control and focus it.
control.activate( {
completeCallback: function() {
control.focus();
}
} );
} else {
// If the `custom` option isn't selected, deactivate the hue color picker and set a default.
control.deactivate( {
completeCallback: function() {
control.setting.set( control.params.defaultValue );
}
} );
}
} );
} );
}( jQuery, wp.customize ) );
由於 $
是 PHP 用來定義變數的特殊字元,同時也是 jQuery 作為選擇器的字元,因此為了避免撰寫程式時發生衝突,WordPress 的 jQuery 必須透過 jQuery("選擇器")
而非習慣的 $("選擇器")
來操縱 DOM 元素,因此透過立即函式的方法,可以讓函式內再度使用較熟悉的 $
。
上述的例子用於 WordPress 佈景主題的 [自訂] 設定,聚焦 (focus) 目前選取的自訂選項。
另一個例子是 Facebook 像素 (Pixel):
!function(b,e,f,g,a,c,d){b.fbq||(a=b.fbq=function(){a.callMethod?a.callMethod.apply(a,arguments):a.queue.push(arguments)},b._fbq||(b._fbq=a),a.push=a,a.loaded=!0,a.version="2.0",a.queue=[],c=e.createElement(f),c.async=!0,c.src=g,d=e.getElementsByTagName(f)[0],d.parentNode.insertBefore(c,d))}(window,document,"script","https://connect.facebook.net/en_US/fbevents.js");
透過 !function
這個方法,檢查當前網站是否已經載入 fbevents.js 這個檔案,以及當前頁面是否已經定義 fbq
這個方法。
今天的文章,講解了程式語言中的變數與變數的型別、運算子,以及函式的基本概念。但你可能注意到,這裡簡化了很多說明,這是因為我們接下來會透過 WordPress 中的一些客製化功能,逐步說明 JavaScript 的用法,因此這裡先概略介紹。
藉由 JavaScript,我們得以動態的控制頁面上的 DOM 元素。什麼是 DOM 元素?就留待明天說明。