《javascript设计模式与开发实践》读书笔记之函数,this,闭包
一.函数基本理论
function compare(val1,val2){
return val1 - val2;
}
var result = compare(5,10);

1,函数的定义没什么意义,之后创建一个字符串,就是函数代码
2,函数执行(被调用)的时候发生的事情:(以上面的代码为例)
创建一个执行环境execution context ,该对象有一个特殊的属性叫[scope chain] 作用域链,属性的值是一个类数组对象,如上图所示,第一个包含了,arguments,val1和val2的活动对象,第二个是包含了compare和result,this的活动对象。
理解函数的基本原理对于函数的理解函数闭包的概念很有帮助。
二.高阶函数
1.函数作为参数传递
最经典的例子就是毁掉函数
var fs = require('fs');
fs.readFile('test.txt',function(data,err){
console.log(data);
});
2.函数作为返回值
作为返回值时候,要注意此时的this指向。
3.函数柯里化
函数柯里化指首先接受一些参数,接受到的参数后不立即执行,而是返回一个新函数,刚才传入的参数在函数形成的闭包中被保存起来,待到真正求值的时候刚才保存的参数才会真正的求值。
var cost = (function(){
var args = [];
return function(){
if(arguments.length===0){
var money =0;
for(var i-0;i<args.length;i++){
money+=args[i];
}
return money;
}else{
[].push.apply(args,arguments);
}
}
})();
cost(100);//
cost(200);//
cost();//
4.函数节流
函数节流的思想就是让一些频繁执行的函数减少执行频率;比如因为浏览器窗口变化引起resize事件的频繁执行,mouseover,上传进度等等。
var throttle = function(fn,interval){
var _self = fn,timer,firstTime;
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);
}
};
window.onresize = throttle(function(){
console.log(1)},500);
代码的解决办法是利用定时器延迟执行,如果定时器在规定时间后还没执行完,那么,下一次执行的时候就不会执行,直接返回;
5.分时函数
分时函数应用的场景比如,你的QQ好友有上千个,每一个好友是一个dom,这是加载的时候浏览器可能吃不消,就要用到setInterval函数来延迟加载。
//ary需要加载的数据,fn加载逻辑,count每一批加载的个数
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=0;i<1000;i++){
ary.push(i);
}
var renderFirendList = timeChunk(ary,function(n){
var div = document.createElement('div');
div.innerHTML = n;
document.body.appendChild(div);
},8);
renderFirendList();
6.惰性加载函数
惰性 加载函数也很常见,比如浏览器嗅探中的时间绑定函数
var addEvent = function(elem,type,handler){
if(window.addEventListener){
return elem.addEventListener(type,handler,false);
}
if(window.addEvent){
return elem.addEvent('on'+type,handler);
}
}
以上代码在非IE浏览器下每次都不会走第二个分支,并且每次添加一个事件就会执行一次判断,虽然这不会增加性能开销,但是可以利用惰性加载来解决
var addEvent = function(elem, type, handler){
if(window.addEventListener){
addEvent = function(elem, type, handler){
elem.addEventListener(type, handler, false)
}
}else if(window.addEvent){
addEvent = function(elem, type, handler){
elem.addEvent('on'+type, handler);
}
}
addEvent(elem,type,handler);
}
三.this
this的判断只要记住一点,就是在执行的时候动态绑定的,而不是函数声明时候绑定,以下是优先级
if(hava new){
this 就是new返回的这个对象
}else if(hava call,apply 绑定){
apply,call绑定的那个对象就是this
}else if(有对象调用){
this就是这个调用的对象
}else{
默认绑定到window //这种情况一般是闭包
}
window.name = 'globalname';
var obj = {};
obj.name = 'lucy';
obj.show = (function(){
console.log(this.name);
return function(){ console.log(this.name)}
})() obj.show();
VM928:6 globalname
VM928:7 lucy
对于上面的代码,obj.show定义为一个对象的方法,但是该方法立即执行,并且是在全局的作用域下执行的,所以输出为globalname,当obj.show执行完之后返回了一个函数赋值给obj.show,说以obj.show此时才真正是对象的方法,所以第二个返回lucy,这个例子完美的证明了运行时动态绑定this。
四.闭包
闭包是有权访问另外一个函数作用域中的变量的函数。《JavaScript高级程序设计第三版》。
典型的例子是一个内部函数访问外部函数的变量,即使这个内部函数返回了或者是被调用了,仍然可以访问外部变量,如下
function com(propertyName){
return function(obj1,obj2){
var value1 = obj1[propertyName];
var value2 = obj2[propertyName];
return value1 - value2;
}
}
var obj1 ={'name':1};
var obj2 ={'name':2};
var compare = com('name');
console.log(compare(obj1,obj2));
上面例子中,匿名函数访问了外部函数的局部变量propertyName,并且当它返回了,而且是在其他地方被调用了仍然可以访问。比如com函数返回了一个匿名函数,并且在其他地方被调用了这个函数,但是仍然可以访问propertyName变量对象,但是有一点就是,这里的propertyName是一个变量对象(活动对象)而不是变量本身,如果是在for等循环语句中就会出现错误。如下面的例子:
function foo(){
var result = [];
for(var i = 0; i < 5; i++){
result[i] = function(){
return i;
}
}
return result;
}
var s = foo();
console.log(s[1]());//
上面代码输出结果是5的原因是每一个内部匿名函数包含的活动对象是i这个变量对象,所以最终foo()执行返回的每一个result[i](这里的i没有变成5是因为它没在匿名函数内),都是外部foo活动对象,所以最终结果就是5.避免这种结果的方法就是在外面继续增加一层作用域,使每一个result[i]函数都持有自己i的活动对象。
function bar(){
var result = [];
for(var j = 0; j < 5; j++){
result[j] = (function(num){
return function(){
return num;
}
})(j)
}
return result;
}
这2段代码的函数活动对象图如下:

第一个代码所有的result都引用函数foo中活动对象i所以当foo执行完返回后,i变量的值是5所以出现如上所示。
第二段代码中,由于参数是按值复制传递的,所以j会一次赋值给num,最内层的匿名函数保存了3个活动对象,分别是立即执行函数,bar,和window,并且立即执行函数也是有5个,并且保存了5个num值,这样就可以达到预期的效果。
《javascript设计模式与开发实践》读书笔记之函数,this,闭包的更多相关文章
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(上)
说来惭愧,4个多月未更新了.4月份以后就开始忙起来了,论文.毕设.毕业旅行等七七八八的事情占据了很多时间,毕业之后开始忙碌的工作,这期间一直想写博客,但是一直没能静下心写.这段时间在看<Java ...
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(下)
上部分主要介绍高阶函数的常见形式,本部分将着重介绍高阶函数的高级应用. 1.currying currying指的是函数柯里化,又称部分求值.一个currying的函数会先接受一些参数,但不立即求值, ...
- Javascript设计模式与开发实践读书笔记(1-3章)
第一章 面向对象的Javascript 1.1 多态在面向对象设计中的应用 多态最根本好处在于,你不必询问对象“你是什么类型”而后根据得到的答案调用对象的某个行为--你只管调用行为就好,剩下的一切 ...
- javascript设计模式与开发实践阅读笔记(4)——单例模式
定义 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 具体来说,就是保证有些对象有且只有一个,比如线程池.全局缓存.浏览器中的window 对象等.在js中单例模式用途很广,比如登录 ...
- javascript设计模式与开发实践阅读笔记(8)——观察者模式
发布-订阅模式,也叫观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 在JavaScript开发中,我们一般用事件模型来替代传统的观察者模式. ...
- javascript设计模式与开发实践阅读笔记(7)——迭代器模式
迭代器模式:指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺 ...
- javascript设计模式与开发实践阅读笔记(6)——代理模式
代理模式:是为一个对象提供一个代用品或占位符,以便控制对它的访问. 代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对 ...
- 《JavaScript设计模式与开发实践》笔记第八章 发布-订阅模式
第八章 发布-订阅模式 发布-订阅模式描述 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布-订阅模式可以广泛应用于 ...
- 《JavaScript设计模式与开发实践》笔记第一章
第一章 面向对象的JavaScript 动态类型语言和鸭子类型 编程语言按照数据类型大体可以分为两类:静态类型语言.动态类型语言. 静态类型语言:在编译时便已确定变量的类型. 优点: 在编译时就能发现 ...
- javascript设计模式与开发实践阅读笔记(5)——策略模式
策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 我的理解就是把各种方法封装成函数,同时存在一个可以调用这些方法的公共函数.这样做的好处是可以消化掉内部的分支判断,使代码效率 ...
随机推荐
- 小K的H5之旅-CSS基础(一)
一.什么是CSS W3C标准中,倡导有3:其一为内容与表现分离,其二为内容与行为分离,其三为内容结构的语义化.其倡导中第一条的"表现"指的便可以说是CSS.CSS全称Cascadi ...
- JavaSE教程-01初识Java-思维导图
图片看不清楚时: 1)可以将图片另存为图片,保存在本地来查看 2)右击在新标签中打开放大查看. 分解: 1.计算机基本概念的普及 硬件 cpu.内存.硬盘等 软件 系统级软件 Windows.Linu ...
- iOS CAShapeLayer、CADisplayLink 实现波浪动画效果
iOS CAShapeLayer.CADisplayLink 实现波浪动画效果 效果图 代码已上传 GitHub:https://github.com/Silence-GitHub/CoreAnima ...
- PHP漏洞之session会话劫持
本文主要介绍针对PHP网站Session劫持.session劫持是一种比较复杂的攻击方法.大部分互联网上的电脑多存在被攻击的危险.这是一种劫持tcp协议的方法,所以几乎所有的局域网,都存在被劫持可能. ...
- EJB基础知识
本人博客文章网址:https://www.peretang.com/basic-knowledge-of-ejb/ 什么是EJB 可移植的, 可重用的, 可伸缩的业务应用程序的平台 为什么选择EJB ...
- guoshiyv 数据结构与算法2-1 线性链式存储
线性链式存储: 包含两部分:1.存储的单个元素 2.指针,指向下一个的地址 typedef struct() { ElementType Data; struct Node *Next; }Lis ...
- 无法启动此程序因为计算机中丢失msvcr71
http://jingyan.baidu.com/article/25648fc1abc4d69190fd0077.html 下面是msvcr文件下载地址: 链接:http://pan.b ...
- vue组件大集合 component
vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...
- .Net WebApi基本操作
一.服务端 1.新建webapi项目 2.配置WebApiConfig public const string DEFAULT_ROUTE_NAME = "DB";// DB指数据 ...
- jquery中div悬浮嵌套按钮效果
<div class="btn_sure_cai" style="margin-left: 0px;" onmouseover="show_hi ...