前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript模式 读书笔记三

JavaScript模式 读书笔记三

作者头像
lilugirl
发布2019-05-28 10:57:35
3150
发布2019-05-28 10:57:35
举报
文章被收录于专栏:前端导学

第四章函数

函数是第一类对象 first-class object,可以作为带有属性和方法的值以及参数进行传递。

创建函数的语法

代码语言:javascript
复制
function foo(){}; //函数声明
var bar=function(){}; //函数表达式
var baz=function baz(){};//函数命名表达式

函数的提升

代码语言:javascript
复制
//反模式
//仅用于掩饰

//全局函数
function foo(){
  alert("global foo");
}
function bar(){
  alert("global bar");
}

function hoisMe(){
  console.log(typeof foo); //输出function
  console.log(typeof bar); //输出undefined
  foo();  //输出local foo
  bar();  //输出 TypeError: bar is not a function

  //函数声明
  //变量 foo以其实现者被提升
  function foo(){
    alert("local foo");
  }

  //函数表达式
  //仅变量 bar被提升
  //函数实现并未被提升
  var bar=function(){
     alert("local bar");
  }


}

hoisMe();

回调示例

代码语言:javascript
复制
//重构findNodes()以接受一个回调函数
var findNodes=function(callback){
  var i=100000,
  nodes=[],
  found;

  if(typeof callback!=="function"){
    callback=false;
  }

  while(i){
    i-=1;
    // 这里是复杂的逻辑...

    //现在进行回调函数
    if(callback){
      callback(found);
    }

    nodes.push(found);

  }
  return nodes;
}

//回调函数
var hide=function(node){
  node.style.display="none";

}
//找到制定节点,并在后续执行中将其隐藏起来
findNodes(hide);
代码语言:javascript
复制
//传递一个匿名回调函数
findNodes(function(node){
  node.style.display="block";
});

回调与作用域

代码语言:javascript
复制
//重构findNodes()以接受一个回调函数
var findNodes=function(callback,callback_obj){
  var i=100000,
  nodes=[],
  found;



  while(i){
    i-=1;
    // 这里是复杂的逻辑...

    //现在进行回调函数
    if(typeof callback==="string"){
      callback=callback_obj[callback];
    }
    if(typeof callback==="function"){
       callback.call(callback_obj,found);
    }

    nodes.push(found);

  }
  return nodes;
}

//回调函数
var myapp={};
myapp.color="green";
myapp.paint=function(node){
  node.style.color=this.color;
};
//找到制定节点,并在后续执行中将其隐藏起来
findNodes(myapp.paint,myapp);

返回函数

代码语言:javascript
复制
var setup=function(){
  alert(1);
  return function(){
    alert(2);
  }
}

//使用setup函数
var my=setup(); //alert1
my(); //alert 2
代码语言:javascript
复制
var setup=function(){
  var count=0;
  return function(){
     return (count+=1);
  }
}

//用法
var next=setup();
next(); //返回1
next(); //返回2
next(); //返回3

自定义函数

惰性函数定义 lazy function definition

代码语言:javascript
复制
var scareMe=function(){
  alert("Boo!");
  scareMe=function(){
    alert("Double boo!");
  }
};

//使用自定义函数
scareMe(); //输出Boo!
scareMe(); //输出Double boo!
代码语言:javascript
复制
var scareMe=function(){
  alert("Boo!");
  scareMe=function(){
    alert("Double boo!");
  }
};

//1 .添加一个新的属性
scareMe.property="properly";

//2. 复制给另一个不同名称的变量
var prank=scareMe;

//3. 作为一个方法使用
var spooky={
  boo:scareMe
};

//calling with a new name
prank(); //输出 Boo!
prank(); //输出 Boo!
 console.log(prank.property); //输出properly

 //作为一个方法来调用
 spooky.boo(); //输出Boo!
 spooky.boo(); //输出Boo!
 console.log(spooky.boo.property); // 输出  properly

 //使用自定义函数
 scareMe(); //输出 Double boo!
 scareMe(); //输出 Double boo!
console.log(scareMe.property); //undefined

即时函数的返回值

即时函数也叫自调用self-invoking 或者自执行self-executing函数。

即时函数中定义的变量将会用于它自身的局部变量,不必担心全局空间被临时的变量污染。

代码语言:javascript
复制
//定义模块module1
(function(){
  //模块1中的所有代码
}());

本例子中即时函数的返回值是一个函数,它将分配给变量getResult,并且将简单地返回res值,该值被预计算并存储在即时函数的闭包中

代码语言:javascript
复制
var getResult=(function(){
  var res=2+2;
  return function(){
    return res;
  }
}());

定义对象属性时也可以使用即时函数

代码语言:javascript
复制
var o={
  message:(function(){
    var who="me",
    what="call";
    return what + " "+who;
  }()),
  getMsg:function(){
    return this.message;
  }
};

//用法
console.log(o.getMsg());  //输出call me
console.log(o.message);   //输出call me

即时对象初始化

immediate object initalization

代码语言:javascript
复制
({
  //在这里可以定义设定值
  //又名配置常数
  maxwidth:600,
  maxheight:400,

  //还可以定义一些实用的方法
  gimmeMax:function(){
    return this.maxwidth+ "X" +this.maxheight;
  },

  //初始化
  init:function(){
    console.log(this.gimmeMax());
    //更多初始化任务。。。
  }

}).init();

初始化时分支

init-time branching 也称为加载时分支 load-time branching 是一种优化模式

代码语言:javascript
复制
//接口
var utils={
  addListener:null,
  removeListener:null
};

//实现 
if(typeof window.addEventListener==="function"){
  utils.addListener=function(el,type,fn){
    el.addEventListener(type,fn,false);
  };
  utils.removeListener=function(el,type,fn){
    el.removeEventListener(type,fn,false);
  }
}else if(typeof document.attachEvent==="function"){  //判断为IE浏览器
  utils.addListener=function(el,type,fn){
    el.attachEvent('on'+type,fn);
  };
  utils.removeListener=function(el,type,fn){
    el.detachEvent("on"+type,fn);
  };

}else{  //更早版本的浏览器 
   utils.addListener=function(el,type,fn){
     el['on'+type]=fn;
   };
   utils.removeListener=function(el,type,fn){
     el['on'+type]=null;
   }
}

函数属性——备忘模式

对于每个函数,它都会自动获得一个length属性,其中包含了该函数期望的参数数量。

代码语言:javascript
复制
function func(a,b,c,d){}
console.log(func.length);

可以在任何时候将自定义属性添加到你的函数中。自定义属性的其中一个用例是缓存函数结果(即返回值),因此下次调用该函数时就不会重做潜在的繁重计算。 缓存函数结果也被称为备忘memoization

代码语言:javascript
复制
var myFunc=function(param){
  if(!myFunc.cache[param]){
    var result={};
    //。。。开销很大的操作。。。
    myFunc.cache[param]=result;
  }
  return myFunc.cache[param];
}
//缓存存储
myFunc.cache={};

配置对象

当需要传递大量参数时,一个更好的办法是仅使用一个参数对象来代替所有参数,该参数对象称为conf,也就是配置的意思。

代码语言:javascript
复制
var conf={
  username:"lilu",
  first:"Yi",
  last:"Liu"
}

function addPerson(person){
  return person.username +" " +person.first+" "+person.last;
}

addPerson(conf);

Curry

函数应用

调用invoking函数和应用applying函数可以得到相同的结果

代码语言:javascript
复制
//定义函数
var sayHi=function(who){
  return "Hello"+ (who?", "+who:"")+"!";
};

//调用函数
sayHi(); //输出Hello
sayHi('world'); //输出Hello,World!

//应用函数
sayHi.apply(null,['hello']); //输出Hello, hello!

Curry化

代码语言:javascript
复制
//curry化的add()函数
//接受部分参数的列表
function add(x,y){
  var oldx=x,oldy=y;
  if(typeof oldy==="undefined"){ //部分
    return function(newy){
      return oldx+newy;
    }
  }
  //完全应用
  return x+y;
}
//测试
typeof add(5); //输出function
add(3)(4); //7
//创建病存储一个新函数
var add2000=add(2000);
add2000(10);//输出2010

一个通用curry化函数

代码语言:javascript
复制
function schonfinkelize(fn){
  var slice=Array.prototype.slice,
    stored_args=slice.call(arguments,1);
  return function(){
    var new_args=slice.call(arguments),
        args=stored_args.concat(new_args);
    return fn.apply(null,args);
  }
}

//普通函数
function add(x,y){
  return x+y;
}

//将一个函数curry化以获得一个新的函数
var newadd=schonfinkelize(add,5);
newadd(4); //输出9

/另一种选择——直接调用新函数
schonfinkelize(add,6)(7);

更多用法

代码语言:javascript
复制
//普通函数
function add(a,b,c,d,e){
  return a+b+c+d+e;
}

//可运行于任意数量的参数
schonfinkelize(add,1,2,3)(5,5); //16

//两步curry化
var addOne=schonfinkelize(add,1);
addOne(10,10,10,10); //输出41

var addSix=schonfinkelize(addOne,2,3);
addSix(5,5); //输出16
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第四章函数
    • 函数的提升
      • 回调示例
        • 回调与作用域
          • 返回函数
            • 自定义函数
              • 即时函数的返回值
                • 即时对象初始化
                  • 初始化时分支
                    • 函数属性——备忘模式
                      • 配置对象
                        • Curry
                          • 函数应用
                          • Curry化
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档