2014年3月7日 星期五

為Array自訂一個方法

Array的方法已經很完善

練習新增一個方法給Array使用
自訂一個和 filter 一模一樣的方法, 稱做 where

建立一個方法:
// 自訂一個和 filter 一模一樣的 function,傳入一個可以回傳 bool 的函式當第二個引數
function where(a, pred) {
    var result = [], n = a.length, j = 0;
    for (var i = 0; i < n; i++) {
        if (!pred(a[i], i)) {
            // 把陣列索引 i 傳入給 pred,而他可以選擇使用或忽略
            // 實際上,標準程式庫中所有的迭代函式(iteration functions),包括 forEach、map、filter,都會把陣列索引傳入給使用者所提供的函式
            continue;
        }
        result[j] = a[i];
        j++;
    }
    return result;
 
}
var a = where([1, 3, 5, 7, 9, 2, 4, 6, 8], function (n) {
    return n < 5;
});
console.log(a); // [1, 3, 2, 4]

將建立的方法給Array使用 : 
// 把自定的 where 方法,加到 Array.prototype,當成陣列的方法
Array.prototype.where = function (pred) {
    var result = [], n = this.length, j = 0;
    for (var i = 0; i < n; i++) {
        if (!pred(this[i], i)) {
            continue;
        }
        result[j] = this[i];
        j++;
    }
    return result;
};
 
var b = [1, 3, 5, 7, 9, 2, 4, 6, 8].where(function (n) { return n < 5; });
console.log(b); // [1, 3, 2, 4]

2014年3月2日 星期日

使用 bind 建立 Curry 函式

保留重複參數的函式,不必每次傳遞


// 一個簡單字串組合函式
function profile(pro, place, name) {
    return 'My name is ' + name + ', I am a ' + pro + ' from ' + place;
}
// 在 profile 上使用 bind 建立 Curry 函式, 也就是建立一個具有所需引數固定子集的代理函式
 
// 新增組合字串方法, 前面兩個參數是固定的, 因為沒有使用到 this, 所以不設定接收者 
var dancer = profile.bind(null, 'dancer', 'Taipei');
dancer('Ian'); // "My name is Ian, I am a dancer from Taipei"
dancer('Joe'); // "My name is Joe, I am a dancer from Taipei"
 
var names = ['Peter', 'Terry', 'Alice'];
var writers = names.map(profile.bind(null, 'writer', 'Tainan'));
console.log(writers);

writers 顯示 :
["My name is Peter, I am a writer from Tainan", "My name is Terry, I am a writer from Tainan", "My name is Alice, I am a writer from Tainan"]

2014年3月1日 星期六

call 和 apply 的用法

call :
theFunction.call(objOfThis, arg1, arg2, ...)

apply :
theFunction.apply(objOfThis, arrayOfArgs)

objOfThis(接收者)如果沒提供參數, 則 global 就會被當成接收者

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession + ".");
}
theFunction("Ian", "programmer");
theFunction.apply(undefined, ["Terry", "dancer"]);
theFunction.call(undefined, "Peter", "writer");

顯示 :
My name is Ian and I am a programmer.
My name is Terry and I am a dancer.
My name is Peter and I am a writer.

call 方法使用在高階函示中

// 建立一個 Table 建構式, 可存放 key-value
function Table(name) {
    this.name = name;
    this.entries = [];
    this.addEntry = function (key, value) {
        this.entries.push({ key: key, value: value });
    };
    // f : 傳入一個方法當 callback, thisArg : 傳入一個物件當接收者
    this.forEach = function (f, thisArg) {
        var entries = this.entries; // 本身的值 (呼叫 forEach 的物件)
        for (var i = 0, n = entries.length; i < n; i++) {
            var entry = entries[i];
            f.call(thisArg, entry.key, entry.value, i);
        }
    };
}
// 實例一個 Table 然後加入一些資料
var tab1 = new Table('tab1');
tab1.addEntry(1, 'apple');
tab1.addEntry(2, 'ball');
tab1.addEntry(3, 'city');
// 再實例一個 Table
var tab2 = new Table('tab2');
// 將tab1的資料複製到tab2
tab1.forEach(tab2.addEntry, tab2);

閉包 Closures - 高階函式 Higher-order functions

高階函示 : 
1. 把其他函式當作引數 (callback function / 回呼函式, 即呼叫時傳入她, 然後她再呼叫回來)
2. 會回傳函式

  • 使用標準程式庫原本的方法

var nums = [1,3,5,7,9,8,6,4,2];
nums.sort(function(x,y){
  if(x<y) return -1;
  if(x>y) return 1;
  return 0;
});
console.log('nums = ' + nums);
 
var names = ['Ian','Peter','Kevin'];
names = names.map(function(name){
    return name.toUpperCase();
});
console.log('names = ' + names);

顯示 :
nums = 1,2,3,4,5,6,7,8,9
names = IAN,PETER,KEVIN


  • 自訂高階函式

// 依照條件建立字串
function buildString(n, callback) {
    var result = '';
    for (var i = 0; i < n; i++) {
        result += callback(i);
    }
    return result;
}
 
// 建立 a~z
var aIndex = 'a'.charCodeAt(0); // 97
var alphabet = buildString(26, function (i) {
    // 這個 callback function 會被執行 26 次, i 接收到的是在 for 迴圈內丟給 callback function 的值, 所以會得到 0 ~ 25
    return String.fromCharCode(aIndex + i);
});
console.log('alphabet = ' + alphabet);
 
// 建立 1~9
var digits = buildString(9, function (i) { return i + 1; });
console.log('digits = ' + digits);
 
// 建立4個亂數
var random = buildString(4, function () {
    return Math.floor(Math.random() * 10);
});
console.log('random = ' + random);

顯示 :
alphabet = abcdefghijklmnopqrstuvwxyz
digits = 123456789
random = 7406