• 《JavaScript设计模式与开发实践》读书笔记-基础知识


    笔记内容多摘录自《JavaScript设计模式与开发实践》(曾探著),侵删。

    面向对象的JavaScript

    1. 动态需要类型和鸭子类型

    • 鸭子类型 如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子
    • 只关注对象的行为,而不关注对象本身,也就是关注has-a,而不是is-a
    • 面向接口编程而不是面向实现编程

    2. 多态

    同一操作作用于不同的对象上,可以产生不同的解释和不同的执行结果。

    多态背后的思想是将“做什么”和“谁去做”以及“怎么做”分离开来,也就是将“不变的事物”与“可能改变的事物分离开”

    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

    用途

    • 改变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));
    

    命令的接收着封闭在闭包中

    闭包与内存管理

    • 误解:内存泄漏

    高阶函数

    函数作为参数传递

    • 回调函数
    • Array.prototype.sort

    函数作为返回值输出

    • 判断数据类型
    • getSingle

    高阶函数实现AOP

    高阶函数的其他应用

    1. currying

    函数柯里化、部分求值

    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);
        };
    };
    
  • 相关阅读:
    利用Oracle分析函数row_number和sys_connect_by_path实现多行数据合并为一行
    public string err属性
    table冻结表头和列[转]
    转:Js日期操作
    ASP.NET中JSON的序列化和反序列化
    javascript Date format(js日期格式化) [转]
    刚开通的博客
    调用图片
    散记兼容,需要整理
    ie6、div高度低于字体大小、则继承fontsize
  • 原文地址:https://www.cnblogs.com/sunven/p/9446432.html
Copyright © 2020-2023  润新知