《JavaScript設計模式與開發實踐》讀書筆記-基礎知識

筆記內容多摘錄自《JavaScript設計模式與開發實踐》(曾探著),侵刪。javascript

面向對象的JavaScript

1. 動態須要類型和鴨子類型

  • 鴨子類型 若是它走起路來像鴨子,叫起來也是鴨子,那麼它就是鴨子
  • 只關注對象的行爲,而不關注對象自己,也就是關注has-a,而不是is-a
  • 面向接口編程而不是面向實現編程

2. 多態

同一操做做用於不一樣的對象上,能夠產生不一樣的解釋和不一樣的執行結果。java

多態背後的思想是將「作什麼」和「誰去作」以及「怎麼作」分離開來,也就是將「不變的事物」與「可能改變的事物分離開」編程

3. 封裝

封裝的目的是將信息隱藏設計模式

4. 原型模式和基於原型繼承的JavaScript對象系統

Object.create = Object.create || function( obj ){
    var F = function(){};
    F.prototype = obj;
    return new F();
}
  • 全部的數據都是對象
  • 要獲得一個對象,不是經過實例化類,而是找到一個對象做爲原型並克隆它
  • 對象會記住它的原型
  • 若是對象沒法響應某個請求,它會把這個請求委託給它的構造器的原型

this、call、apply

this

this的指向閉包

  • 做爲對象的方法調用
  • 做爲普通函數調用
  • 構造器調用
  • Function.prototype.call或Function.prototype.apply調用

call和apply

用途app

  • 改變this指向
  • Function.prototype.bind
  • 借用其餘對象的方法

閉包和高階函數

閉包

變量的做用域

變量的生命週期

閉包的做用

  • 封裝變量
  • 延續局部變量的壽命

閉包和麪向對象設計

用閉包實現命名模式

把請求封裝爲對象,分離請求發起者和接收者(執行者)之間的耦合關係函數

var Tv = {
    open: function () {
        console.log('打開電視機');
    },

    close: function () {
        console.log('關上電視機');
    }
};

var createCommand = function (receiver) {
    var execute = function () {
        return receiver.open(); // 執行命令,打開電視機
    }
    var undo = function () {
        return receiver.close(); // 執行命令,關閉電視機
    }
    return {
        execute: execute,
        undo: undo
    }
};

var setCommand = function (command) {
    document.getElementById('execute').onclick = function () {
        command.execute(); // 輸出:打開電視機
    }
    document.getElementById('undo').onclick = function () {
        command.undo(); // 輸出:關閉電視機
    }
};

setCommand(createCommand(Tv));

命令的接收着封閉在閉包中this

閉包與內存管理

  • 誤解:內存泄漏

高階函數

函數做爲參數傳遞

  • 回調函數
  • Array.prototype.sort

函數做爲返回值輸出

  • 判斷數據類型
  • getSingle

高階函數實現AOP

高階函數的其餘應用

1. currying

函數柯里化、部分求值prototype

var currying = function (fn) {
    var args = [];
    return function () {
        if (arguments.length === 0) {
            return fn.apply(this, args);
        } else {
            [].push.apply(args, arguments);
            return arguments.callee;
        }
    }
};
var cost = (function () {
    var money = 0;
    return function () {
        for (var i = 0, l = arguments.length; i < l; i++) {
            money += arguments[i];
        }
        return money;
    }
})();

var cost = currying(cost); // 轉化成currying 函數
cost(100); // 未真正求值
cost(200); // 未真正求值
cost(300); // 未真正求值
alert(cost()); // 求值並輸出:600
2. uncurrying

泛化this的提取過程設計

Function.prototype.uncurrying = function () {
    var self = this;
    return function () {
        var obj = Array.prototype.shift.call(arguments);
        return self.apply(obj, arguments);
    };
};
Function.prototype.uncurrying = function () {
    var self = this;
    return function () {
        return Function.prototype.call.apply(self, arguments);
    }
};
3. 函數節流
var throttle = function (fn, interval) {
    var __self = fn, // 保存須要被延遲執行的函數引用
        timer, // 定時器
        firstTime = true; // 是不是第一次調用
    return function () {
        var args = arguments,
            __me = this;
        if (firstTime) { // 若是是第一次調用,不需延遲執行
            __self.apply(__me, args);
            return firstTime = false;
        }
        if (timer) { // 若是定時器還在,說明前一次延遲執行尚未完成
            return false;

            timer = setTimeout(function () { // 延遲一段時間執行
                clearTimeout(timer);
                timer = null;
                __self.apply(__me, args);
            }, interval || 500);
        };
    }
};
4. 分時函數
var timeChunk = function (ary, fn, count) {
    var obj,
        t;
    var len = ary.length;
    var start = function () {
        for (var i = 0; i < Math.min(count || 1, ary.length); i++) {
            var obj = ary.shift();
            fn(obj);
        }
    };
    return function () {
        t = setInterval(function () {
            if (ary.length === 0) { // 若是所有節點都已經被建立好
                return clearInterval(t);
            }
            start();
        }, 200); // 分批執行的時間間隔,也能夠用參數的形式傳入
    };
};

var ary = [];
for (var i = 1; i <= 1000; i++) {
    ary.push(i);
};
var renderFriendList = timeChunk(ary, function (n) {
    var div = document.createElement('div');
    div.innerHTML = n;
    document.body.appendChild(div);
}, 8);
renderFriendList();
5. 惰性加載函數
var addEvent = function (elem, type, handler) {
    if (window.addEventListener) {
        addEvent = function (elem, type, handler) {
            elem.addEventListener(type, handler, false);
        }
    } else if (window.attachEvent) {
        addEvent = function (elem, type, handler) {
            elem.attachEvent('on' + type, handler);
        }
    }
    addEvent(elem, type, handler);
};

var div = document.getElementById('div1');
addEvent(div, 'click', function () {
    alert(1);
});
addEvent(div, 'click', function () {
    alert(2);
});
6. 函數防抖
var debounce = function (method, delay) {
    var timer = null;
    return function () {
        var _this = this;
        var args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
            method.apply(_this, args);
        }, delay);
    };
};
相關文章
相關標籤/搜索