JavaScript: The Good Parts

Methods & Styles

Agenda

  • JavaScript 常見的"方法 "
  • JavaScript 的 Coding Style

常見的"方法"

今天將會提到的方法

  • Array
  • Function
  • Number
  • Object
  • RegExp
  • String

Array

Array

  • sort
  • concat
  • join
  • pop
  • push
  • reverse
  • shift
  • slice
  • splice
  • unshift

Array.sort

//  用法 array.sort(compareFn)
//  排序array內容

var array = [12, 8, 41];

array.sort();

// 預期:   [8, 12, 41]
// output: [12, 41, 8] (unexpected result)

sort沒那麼聰明

sort 預設會array內的元素轉成字串, 導致排序的結果可能會不如預期

自訂排序函數

Array.sort

//  用法 array.sort(compareFn)
//  排序array內容
//  比較函數: compareFn, 應傳入兩個參數,
//  當compareFn回傳是負數, 則第一個參數放入array的優先權較高
//  當compareFn回傳是正數, 則第二個參數放入array的優先權較高
//  當compareFn回傳0 代表兩參數放入array的優先權相同

var array = [12, 8, 41];
var ascFn = function(a, b){
    return a-b
}

array.sort(ascFn);

// 預期:  [8, 12, 41]
// output: [8, 12, 41] good!

Array.concat

//  用法 array.concat(item, item, ...)
//  將item加入到array的末端, item可以是array, object, boolean, undefined, null
//  ※ item若是array, concat則會將item內的元素一一取出並加入array末端

var target = ["a1", "a2", "a3"];
var source = ["b1", "b2", "b3"];

var concatArray = [];

concatArray = target.concat(source, "c1", true, undefined, null, {"a": "123"}, function aaa(){});

// output: ["a1", "a2", "a3", "b1", "b2", "b3", "c1", true, undefined, null, Object, function] 

Array.join

//  用法: array.join(separator)
//  separator: 用來區隔array合併成String時, 區隔各個元素的符號

var date= ["2017", "01", "01"]

var rs = ""

rs = date.join("-")


// output: "2017-01-01"

Array.pop

//  用法: array.pop()
//  移除並回傳array最後一個元素

var array= ["a", "b", "c"]

var rs = array.pop();

// rs = "c";

Array.push

//  用法: array.push(item)
//  將item加入array最後一個位置
//  ※ 與concat不同之處: push會回傳array的新長度

var array= ["a", "b", "c"]

var rs = array.push("d");

// rs = 4;

Array.push

//  用法: array.push(item)
//  將item加入array最後一個位置
//  ※ 與concat不同之處: push會回傳array的新長度

var array= ["a", "b", "c"]

var rs = array.push("d");

// rs = 4;

Array.reverse

//  用法: array.reverse()
//  反轉array內元素的順序, 並回傳array

var array = ["a", "b", "c"]

var rs = array.reverse();

// rs= ["c", "b", "a"];

Array.shift

//  用法: array.shift()
//  移除並回傳array第一個元素
//  ※ shift通常比pop速度慢很多 

var array = ["a", "b", "c"]

var rs = array.shift();

// rs = "a";
// array = ["b", "c"];

Array.slice

//  用法: array.slice(start, end)
//  slice將從start位置開始複製元素, 一直到end的位置則停止複製, 並將複製的元素加入到一個新的array, 最後回傳新array
//  start: 可不填寫, 預設為 0
//  end: 可不填寫, 預設為array.length 

var array = ["a", "b", "c"]

var rs1 = array.slice(1, 2);
var rs2 = array.slice(1);

// rs1 = ["b"]
// rs2 = ["b", "c"]

Array.splice

//  用法: array.splice(start, deleteCount, item)
//  splice將從start位置開始移除deleteCount個元素,並以item取代, 最後將移除的元素放入新的array內回傳
//  常見用途: 刪除元素

var array = ["a", "b", "c"]

var rs = array.splice(1, 1, "bbb");

// rs = ["b"]
// array = ["a", "bbb", "c"]

Array.unshift

//  用法: array.unshift(item, ...)
//  將item加入array最前端
//  ※ 與push類似, 不同之處: push將item加入array末端, 並回傳array的新長度

var array = ["a", "b", "c"]

var rs = array.unshift("ddd", "eee");

// rs = 5
// array = ["ddd", "eee", "a", "b", "c"]

Function

function.apply

var a  = function(a1, a2, a3){
  
    this.list = [a1, a2, a3]
    return this
}


// try below
var rs = a.apply(null, ["a", "b", "c", "d"])
var rs = a.apply({}, ["a", "b", "c", "d"])

function.apply

Function.method("bind", function(that){
    console.log("that===========>", that);
    console.log("this===========>", this);
    var method = this,
        slice = Array.prototype.slice,
        args = slice.apply(arguments, [1]) 

    console.log("slice.apply(arguments, [1])============>", slice.apply(arguments, [1]))
    console.log("slice.apply(arguments, [0])============>", slice.apply(arguments, [0]))
    console.log("args.concat(slice.apply(arguments, [0])====>", args.concat(slice.apply(arguments, [0])));

    return function(){
        return method.apply(that, 
            args.concat(slice.apply(arguments, [0]))
        )
    }
});

var x = function(){
    return this.value;
}.bind({value: 666});

alert(x()); ///666

//make a method available to all functions by augmenting Function.prototype 
Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

Number

Number

  • toExponential
  • toFixed
  • toPrecision
  • toString

Number.toFixed

//  用法 Number.toFixed(fractionDigits)
//  四捨五入小數點後方第fractionDigits+1的數字, 並回傳整數以及小數點後方第fractionDigits位置
//  ※ 回傳值為字串屬性
//  0 <= fractionDigits <= 20

var num= 9487.9487;

num.toFixed(2);

// output: "9487.95"

Number.toPrecision

//  用法 Number.toPrecision(precision)
//  確保回傳n個整數位以及小數後後面precision-n個位數, 並先四捨五入小數點後方precision-n+1的數字
//  常用在"無理數", 也就是小數點後方有無限多個數字
//  ※ 回傳值為字串屬性
//  precision預設是16
//  1 <= precision <= 21

var num= 9487.9487;

num.toPrecision(5);

// output: "9487.9"


num.toPrecision(3);

// output: "9.49e+3"

Number.toString

//  用法 Number.toString(radix)
//  可將數字轉成"radix進位"後, 再轉成字串格式回傳
//  radix預設是10
//  2 <= radix <= 36

var num= 8;

num.toString(2);


// output: "1000"

Object

Object.hasOwnProperty

//  用法 Object.hasOwnProperty(name)
//  檢查Object內是否有name這個屬性
//  ※ 回傳值為bool值

var a = {"val": "123"}

a.hasOwnProperty("val")    // output: true
a.hasOwnProperty("val1")   // output: false

// 不檢查Object預設給的prototype屬性
a.hasOwnProperty("hasOwnProperty")   // output: false

RegExp

RegExp

  • exec
  • test

regexp.exec()

//  用法 regexp.exec(str)
//  用正規表示法比對str
//  若有找到符合規則的字串, 則回傳陣列, 陣列的第一個位置代表與regexp符合的字串
//  當無法在str內找到符合的字串ㄝ, 則會傳null
//  ※ 最強大,但速度最慢的正規示使用方法

/Example 1: 正規表示法內加上"g" /
var myRe = /ab*/g;
var str = 'abbcdefabh';
var myArray;
myArray = myRe.exec(str)   // 第一次執行, 回傳:["abb", index: 0, input: "abbcdefabh"]
myArray = myRe.exec(str)   // 第二次執行, 回傳:["ab", index: 7, input: "abbcdefabh"]

/Example 2: 正規表示法後方不加上"g" /
var myRe = /ab*/;
var str = 'abbcdefabh';
var myArray;
myArray = myRe.exec(str)   // 第一次執行, 回傳:["abb", index: 0, input: "abbcdefabh"]
myArray = myRe.exec(str)   // 第二次執行, 回傳:["abb", index: 0, input: "abbcdefabh"]

regexp.test()

//  用法 regexp.test(str)
//  str符合regexp規則則回傳true, 否則回傳false
//  ※ regexp不能加入"g", 與test一起併用
//  最簡單, 也最快的正規表示方法

var myRe = /ab*/;
var str = 'abbcdefabh';
var myArray;
myArray = myRe.test(str)   // true

String

String

  • charAt
  • charCodeAt
  • concat
  • IndexOf
  • lastIndexOf
  • localeCompare
  • match
  • replace
  • search
  • slice
  • split
  • substring
  • toLocaleLower
  • toLowerCase
  • UpperCase
  • fromCharCode

方法太多, 就不一一介紹了

今天就介紹幾個MDN 是神物

名稱 charAt(pos) charCodeAt(pos)
功能 回傳pos位置上的字元 回傳pos位置字元的code point值
差異 回傳值: 字元 回傳值: code point值
範例 let name = "ceall"
let char = name.charAt(1);

// char = "e"
let name = "ceall"
let char = name.charCodeAt(1);

// char = 101

charAt VS charCodeAt

名稱 indexOf (searchStr, pos) lastIndexOf (searchStr, pos)
功能 回傳searchStr在string位置中的索引值。
pos: optional, 可指定搜尋的起始位置
回傳searchStr在string位置中的索引值
pos: optional, 可指定搜尋的起始位置
差異 從頭開始搜尋 從末端開始搜尋
範例 let name = "Mississippi"
let index = name.indexOf ("ss");
// index = 2

index = name.indexOf ("ss",  3);
// index = 5

index = name.indexOf ("ss",  6);
// index = -1
let name = "Mississippi"
let index = name.lastIndexOf("ss");
// index = 5

index = name.lastIndexOf("ss",  3);
// index = 2

index = name.lastIndexOf("ss",  6);
// index = 5

indexOf VS lastIndexOf

String.localeCompare

//  用法 String.localeCompare(that)
//  string 與that比較, 比較兩string的第一個字元
//  that順序在string前面則回傳1, 反之回傳-1

var a = "abc"
var b = "bac"

a.localeCompare(b)

//output: -1

var arr = ['AAA', 'A', 'aa', 'a', 'Aa', 'aaa']
m.sort(function (a, b){
    return a.localeCompare(b);
})

//m: ["a", "A", "aa", "Aa", "aaa", "AAA"]

String.match

//  用法 String.match(regexp)
//  regexp沒有包含標籤"g", 則運行的方式與regexp.exec(string)相同
//  如果有包含標籤"g", 

//沒有標籤'g'
var myRe = /ab*/;
var str = 'abbcdefabh';

str.match(myRe)    //output: ["abb", index: 0, input: "abbcdefabh"]

//有標籤'g'

var myRe = /ab*/g;
var str = 'abbcdefabh';

str.match(myRe)    //output: ["abb", "ab"]

String.replace

//  用法 String.replace(searchValue, replaceValue)
//  searchValue若為字串, 則只有第一個出現的searchValue被取代
//  searchValue若為正規表示法. 並且包含標籤'g', 則所有searchValue將都被取代, 若沒有加入標籤'g', 則只會取代第一個出現的searchValue
//  replaceValue可以是自串, 也可以是function

// 範例1
var str = "apples are round, and apples are juicy.";
var newstr = str.replace("apples", "oranges");

// output: "oranges are round, and apples are juicy."

// 範例2
var re = /apples/gi;
var str = "Apples are round, and apples are juicy.";
var newstr = str.replace(re, "oranges");

// output: "oranges are round, and oranges are juicy."

// 範例3

var re = /(\w+)\s(\w+)/;
var str = "John Smith";  
str.match(re)  // ["John Smith", "John", "Smith", index: 0, input: "John Smith"]
var newstr = str.replace(re, "$2, $1");  // "Smith, John"

//範例4

var str = "apples are round, and apples are juicy.";
var newstr = str.replace(/apples/gi, function(arg1, arg2, arg3){
// arg1 符合正規表示式的字串
// 字串的位置索引值
// str字串

console.log("arg1", arg1)  // apples,  apples
console.log("arg2", arg2)  // 0,  22
console.log("arg3", arg3)  // "apples are round, and apples are juicy.", "apples are round, and apples are juicy."
});

String.search

//  用法 String.search(regexp)
//  回傳符合正規表示示規則的字串片段位置, 若搜尋失敗則回傳-1
//  若加入標籤"g", 則將被忽略

var myRe = /ab*/;
var str = 'abbcdefabh';

str.search(myRe)   // 0

String.slice

//  用法 String.slice(start, end)
//  方法與參數的定義同Array
//  start代表slice複製字元的起點, 若是複製cnt個字元, 則end = start + cnt;

let str = "An apple a day, keeps the doctor away"

let getApple = str.slice(3, 8);       // "apple"
let getSecSentence = str.slice(-21)   // "keeps the doctor away"

String.split

//  用法 String.split(separator, limit)
//  split依照separator分割字串, 並將分割的元素放入新的字串
//  separator可以是符號也可以是正規表示式
//  limit: 分割後, 新的array內的元素數量最多不能超過limit

let str = "012345"

str.split('',2);  //  ["0", "1"] (本書解答有誤)

String.substring

//  用法 String.substring(start, end)
//  與slice方法一致
//  不同之處: 參數不能帶負數
//  substring, slice擇一使用即可

String.toLocaleLowerCase

//  用法 String.toLocaleLowerCase()
// 將所有字母轉換成小寫, 並依主機目前環境設定列入考慮
// 因土耳其語的某些字母轉換成小寫與英語不同, toLowerCase反而不實用

String.fromCharCode

//  用法 String.fromCharCode(char, ...)
//  char, 輸入數值
//  fromCharCode將數值轉換成字串

var a = String.fromCharCode(67, 97, 116);  // "Cat"

Coding Style

Why ?

Reasons

  • 需要考慮到未來修改程式結構的可能性
  • 增加易讀性
    • 易讀性高的code會提高工程師工作意願的可能性

What are the suggestions?

Suggestions

  • 每次縮排空四個空格
  • '(', '{' 等符號, 皆在前方加入空格 
    • ex:  if () {};
  • 盡量一句敘述就一行
  • 逗號或雙元運算子(!=, ==)後才換行
    • 避免JavaScript自動加入分號時造成錯誤
  • 需更新註解
  • 區塊型註解用來較正式的說明或是關閉原始碼的說明
  • 應該每個程式開端宣告所有變數
    • JavaScript允許變數可在被使用後才宣告
  • 善用closure建立資訊隱藏

Title Text

Javascript Good Part - Javascript Methods & Coding Styles介紹

By ceall

Javascript Good Part - Javascript Methods & Coding Styles介紹

  • 974