高级函数

安全的类型检测

  • js内置的类型检测并非完全可靠,typeof操作符难以判断某个值是否为函数
  • instanceof在多个frame的情况下,会出现问题。
    例如:var isArray = value instance of Array ;
    会由于存在多个window,而value与Array不属于同个window的情况而导致出错

对于这样的问题,最好的解决方法是通过调用Object的toString方法,例如:

 function isArray(){
return Object.prototype.toString.call(value) == "[object Array]";
}

注意,这个技巧前提是Object.prototype.toString方法未被修改过

作用域安全的构造函数

调用构造函数的时候,如果忘记写new的话,构造函数中对this的赋值,则可能会赋值到window上成为全局变量,导致其他错误。
可以在构造函数增加判断来避免这种错误,如下:

 function Person(name){
if(this instanceof Person){
this.name = name;
}else{
return new Person(name)
}
}

惰性载入函数

在程序中 ,类似对浏览器的检测等,进行一次检测过后,只要在当前环境下,其检测结果都不会改变。所以,我们的函数中 if 语句只需要判断一次就可以了,而不需要每次都执行。
对这种情况的解决方案便称为惰性载入。
惰性载入表示函数执行的分支仅会发生一次。

惰性载入两种实现方法:
  • 替换真正执行的方法,伪代码如下:
  1.  function foo(){
    if(someCheck){
    foo =function(){doSomeThing()};
    }else{
    foo =function(){doAnotherSomeThing()};
    }
    }
  • 声明函数时就指定适当的函数。通过匿名自执行函数
  •  var foo =function(){
    if(someCheck){
    returnfunction(){doSomeThing()};
    }else{
    returnfunction(){doAnotherSomeThing()};
    }
    }();

这样,在代码首次载入的时候,就已经得到对应的值了

函数绑定

先看一个例子:

 var handler ={
message:"handler message",
handlerClick:function(event){
console.log(this.message);
}
}
//用于将某个函数绑定到指定环境
var bind =function(fn, context){
returnfunction(){
fn.apply(context, arguments);
}
};
var nomalBtn = document.getElementById("nomalBtn");
var bindBtn = document.getElementById("bindBtn");
nomalBtn.addEventListener("click", handler.handlerClick,false);//点击时候会打印 undefined
bindBtn.addEventListener("click", bind(handler.handlerClick,handler),false);//点击按钮会打印 handler.message的值

在上面的例子中,我们需要对象中的方法作为事件处理程序。但是,当事件触发时,this的指向却不是handler而是按钮本身。
解决方法可以使用匿名函数,但是,过多的匿名函数会令代码变的难于理解与调试,因此,推荐使用bind方法。

ES5 为函数定义了一个原生的bind方法,也就是说,你不必自己实现bind方法,只需要直接在函数上调用即可handler.handlerClick.bind(handler) ;

函数科里化

函数科里化是用于创建已经设置好一个或多个参数的函数。缩小了函数的适用范围,但提高函数的适性。
例如:

  

 //普通的add版本
function add(num1, num2){
return num1 + num2;
}
//第一个参数为5的add版本
function curriedAdd5(num2){
return add(5, num2)
}

上面只是一个展示柯里化概念的例子。创建柯里化函数有一个通用方式:

 function curry(fn, context){
//截取调用curry时候,除了fn,context,之后的所有参数
var args =[].slice.call(arguments,2);
returnfunction(){
//获取调用fn的所有参数
var totalArgs = args.concat([].slice.call(arguments));
return fn.apply(context, totalArgs);
}
}

这样,上面的例子中curriedAdd5可以用另一个方法来创建 var curriedAdd5 = curry(add, null, 5)

javascript中的柯里化函数和bind函数提供了强大的动态函数创建功能,但是两者都不应该滥用,因为每个函数都带来额外的开销

javascript高级函数的更多相关文章

  1. 前端常用的库和实用技术之JavaScript高级函数

    1.惰性载入函数 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  2. JavaScript高级 函数表达式 《JavaScript高级程序设计(第三版)》

    函数表达式的特征 使用函数实现递归 使用闭包定义私有变量 前面我们说到定义函数有两种方式:函数声明.函数表达式. 两者的区别在于函数声明提升,前者在执行之前的上下文环境中直接被赋值,而后者不会. 一. ...

  3. JavaScript高级之函数的四种调用形式

    主要内容 分析函数的四种调用形式 弄清楚函数中this的意义 明确构造函对象的过程 学会使用上下文调用函数 了解函数的调用过程有助于深入学习与分析JavaScript代码. 本文是JavaScript ...

  4. (读书笔记)函数参数浅析-JavaScript高级程序设计(第3版)

    ECMAScript函数不介意传递的参数个数,因为在其内部是用一个数组进行表示的.在函数体内可以通过arguments对象来访问这个参数数组,就像我们正常访问数组一样处理. arguments对象只是 ...

  5. JavaScript系列:高级函数篇

    前言: 本篇主要是介绍 JavaScript使用函数的高级方法,函数是JavaSCript中最有趣的部分,利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:函数回调,高阶函数以及函 ...

  6. 一篇文章把你带入到JavaScript中的闭包与高级函数

    在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. funct ...

  7. JavaScript高级程序设计(读书笔记)之函数表达式

    定义函数的方式有两种:一种是函数声明,另一种就是函数表达式. 函数声明的一个重要特征就是函数声明提升(function declaration hoisting),意思是在执行代码前会先读取函数声明. ...

  8. Javascript高级程序设计——this、闭包、函数表达式

    在javascript中函数声明会被提升,而函数表达式不会被提升.当函数执行时,会创建一个执行环境和相应的作用域链,然后利用arguments和其他的命名参数的值来初始化函数的活动对象,作用域链链中所 ...

  9. 学习javaScript必知必会(3)~数组(数组创建,for...in遍历,辅助函数,高级函数filter、map、reduce)

    一.数组: 1.js是弱语言,js中的数组定义时:不用指定数据类型.不用功指定数组长度:数组可以存储任何数据类型的数据 2.数组定义的[ ] 的实质: [] = new Array(); {} = n ...

随机推荐

  1. 为什么使用 Redis及其产品定位 (转载自http://www.infoq.com/cn/articles/tq-why-choose-redis)

    传统MySQL+Memcached架构遇到的问题 实际MySQL 是适合进行海量存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不 ...

  2. 实现QQ机器人报警

    如题,废话不说,直接上代码.首先是登录QQ的小脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...

  3. sql,插入最大值加1

    insert into aa (id,name) values((select case when max(id) is null then 1 else max(id)+1 end from aa) ...

  4. 【easyui】—easyui教你编写一个前台的架子

    以前做项目都是在别人搭建好的环境下直接编写单独的页面,也没有处理过怎么搭建一个框架.看到别人的布局都挺好的,自己也想做一个走一下流程. 嘿,刚开始时看着别人写的代码,去找怎么写. 这是我自己的想法,使 ...

  5. Struts2中的namespace使用

    namespace一般在项目比较复杂的情况下使用较好. 在struts2的项目中,namespace主要在以下环境中常使用: 1. 在配置文件中(struts.xml)以及被它包含的XX.xml文件中 ...

  6. delphi的多线程编程

    多线程的基本概念 win 98/nt/2000/xp 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用cpu 运行时间和资源,或者说,把cpu 时间划成片,每个片分给不同的线程 ...

  7. 配置《算法 第四版》的Eclipse开发环境

    1. 安装JAVA JAVA网址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 配置环境变量(我把JAVA安装在 ...

  8. pyenv

    export PYTHON_BUILD_MIRROR_URL="http://pyenv.qiniudn.com/pythons/"

  9. poj 3259 Wormholes

    题目连接 http://poj.org/problem?id=3259 Wormholes Description While exploring his many farms, Farmer Joh ...

  10. Windows server 2012清除并重建SID

    首先介绍下什么是SID SID也就是安全标识符(Security Identifiers),是标识用户.组和计算机帐户的唯一的号码.在第一次创建该帐户时,将给网络上的每一个帐户发布一个唯一的 SID. ...