在ECMAScript中,Function(函数)类型实际上是对象。每个函数也是Function类型的实例,而且都与其它引用类型一样具有属性和方法。由于是函数对象,因此函数名实际上也是一个指向函数对象的指针。

一、函数的声明方式

  函数通常是使用函数声明语法定义:

  1、普通的函数声明

  function sum(sum1,sum2){

  return sum1+sum2;

  }

  2、使用变量初始化函数

  var sum=function(){

  return sum1+sum2;

  }

  3、使用function构造函数

  var sum=new Function("sum1","sum2","return sum1+sum2");  //不推荐 因为这种会导致解析两次代码,一次解析常规ECMAScript,一次解析传入构造函数中的字符串

二、作为值类型

  因为ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另外一个函数,而且可以将一个函数作为另一个函数的结果返回。

  function callSomeFunction(someFunction,someArgument){

    return someFunction(someArgument);

  }

  这个函数接受两个参数。第一个参数应该是一个函数,第二个参数应该是要传递给该函数的一个值。

  function someFunction(someArgument){

    return  someArgument+100;

  }

  var result=callSomeFunction(someFunction,100);     //200

三、函数内部属性

在函数内部,有两个特殊的对象:agruments和this。其中,arguments是一个类型组对象,包含着传入函数中的所有参数。虽然arguments的主要用途是保存函数参数,但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

  function factorial(num){

    if(num<=1){

      return  1;

    } else {

      return num * factorial(num-1);

    }

  }

  定义阶乘函数一般用到递归算法;如果上面的代码所示,在函数有名字,而且名字以后也不会变的情况下,这样定义是没有问题的。但问题是这个函数的执行与函数名factorial紧紧耦合在一起。为了消除这种紧密耦合的现象,可以像下面这样使用arguments.callee。

  function factorial(num){

    if(num <= 1){

      return 1;

    } else {

      return num * arguments.callee(num - 1);

    }

  }

  在这个重写后的factorial()函数体内,没有再引用函数名factorial。这样,无论引用函数时使用的是什么名字,都可以保存正常完成递归调用。

  var trueFactorial=factorial;

  factorial=function(){

    return 0;

  }

  alert(trueFactorial(5));  //120

  alert(factorial(5));        //0

  函数内部另外一个对象是this,其行为与java和C#中的this大致相同。this引用的是函数据以执行操作对象,或则说函数调用语句所处的那个作用域。

  window.color = "red";

  var o = { color : "blue";};

  function sayColor(){

    alert(this.color);

  }

  sayColor();           //red

  o.sayColor = sayColor;

  o.sayColor();      //blue

  上面这个函数sayColor()是在全局作用域中定义的,它引用了this对象。由于在调用函数之前,this的值不确定,因此this可能会在代码执行过程中引用不同的对象。当在全局作用域中调用sayColor()时,this引用的是全局对象window;换句话说,对this.color求值会转换成对window.color求值,于是结果就返回了“red”。而当把这个函数赋值给对象o并调用o.sayColor()时,this引用的对象o,因此对this.color求值会转换成对o.color求值,结果就返回了“blue”;

  备注:函数名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境中执行,全局的sayColor()函数与o.sayColor()指向的任然是同一个函数。

四、函数属性和方法

  每个函数包含两个属性:length和prototype。其中,length属性表示函数希望接受的命名参数的个数:

  function sayName(name){

    alert(name);

  }

  function sum(num1,num2){

    reutrn num1 + num2 ;

  }

  function sayHi(){

    alert("hi");

  }

  alert(sayName.length);  //1

  alert(sum.length);        //2

  alert(sayHi.length);      //0

  以上三个函数,每个函数接受的命名参数个数不同。

  每个函数都包含两个非继承而来的方法:apply()和call()。这个两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。首先,apply()方法接收两个参数:一个是在其中运行函数的作用域,另外一个是参数数组。其中,第二个参数可以是Array的实例,也可以使arguments对象。

  function sum(sum1,sun2){

    return sum1 + sum2;

  }

  function callSum1(num1,num2){

    return sum.apply(this,arguments);   //传入arguments对象

  }

  function callSum2(num1,num2){

    return sum.apply(this,[num1,num2]);   //传入数组

  }

  alert(callSum1(10,10)); //20

  alert(callSum2(10,10));//20

  call()方法和 apply()方法的作用相同,他们的区别仅在于接受参数的方法不同。对于call()方法而言,第一个参数是this值没有变法,变法的是其余参数都直接传递给函数。换句话说,在使用call方法时,传递给函数的参数必须一个个的列举出来。

  function sum(sum1,sum2){

    return num1 + num2;

  }

  function callSum(num1,num2){

    return sum.call(this,num1,num2);

  }

  alert(callSum(10,10));  //20

  事实上,传递参数并非apply()和call()真正的用武之地;他们真正强大的地方是能够扩充函数赖以运行的作用域。

  window.color = "red";

  var o = { color : "blue" };

  function sayColor(){

    alert(this.color);

  }

  sayColor();                //red

  sayColor.call(this);    //red

  sayColor.call(window);  //red

  sayColor.call(o);     //blue

第十一章 Function类型的更多相关文章

  1. 第十一章 管理类型(In .net4.5) 之 管理对象的生命周期

    1. 概述 本章内容包括 管理非托管资源.使用IDisposable接口 以及 管理析构器和垃圾回收. 2. 主要内容 2.1 理解垃圾回收机制 ① 代码执行的时候,内存中有两个地方存放数据项:堆 和 ...

  2. 小红书第五章——引用类型之function类型

    有趣的函数——function类型 函数实际上是对象,每个函数都是function类型的实例,具有属性和方法. 1.函数的定义方法 1)函数声明语法 function sum(num1,num2){/ ...

  3. sql 入门经典(第五版) Ryan Stephens 学习笔记 (第六,七,八,九,十章,十一章,十二章)

    第六章: 管理数据库事务 事务 是 由第五章 数据操作语言完成的  DML ,是对数据库锁做的一个操作或者修改. 所有事务都有开始和结束 事务可以被保存和撤销 如果事务在中途失败,事务中的任何部分都不 ...

  4. JS复习:第十、十一章

    第十章 NodeList是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点,但它并不是Array实例,将其转化为数组的方法: function converToArray(nodes ...

  5. jQuery第十一章

    第十一章 一.jQuery性能优化 1.使用最新版本的jQuery类库. 2.使用合适的选择器 (1)$(“#id”) :使用id来定位DOM元素是最佳提高性能的方式. (2)$(“p”) :标签选择 ...

  6. D3.js的v5版本入门教程(第十一章)——交互式操作

    D3.js的v5版本入门教程(第十一章) 与图形进行交互操作是很重要的!所谓的交互操作也就是为图形元素添加监听事件,比如说当你鼠标放在某个图形元素上面的时候,就会显示相应的文字,而当鼠标移开后,文字就 ...

  7. 第十一章 前端开发-JavaScript

    第十一章 前端开发-JavaScript 11.3.1 js引入方式 行内样式 <p id="" class="" style="" ...

  8. Flask 教程 第二十一章:用户通知

    本文翻译自The Flask Mega-Tutorial Part XXI: User Notifications 这是Flask Mega-Tutorial系列的第二十一章,我将添加一个私有消息功能 ...

  9. 第十一章 TClientDataSet

    第十一章 TClientDataSet 与TTable.TQuery一样,TClientDataSet也是从TDataSet继承下来的,它通常用于多层体系结构的客户端.TClientDataSet最大 ...

随机推荐

  1. Oracle 参数化更新数据时报错:Oracle ORA-01722: 无效数字

    报错:Oracle ORA-01722: 无效数字 看了一篇博客,据说是参数与列名不能一致,改过之后还是报一样的错误:Oracle ORA-01722: 无效数字 ,后来试了一下,不是参数名必须不一样 ...

  2. java并发之CountDownLatch、Semaphore和CyclicBarrier

    JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch.Semaphore和CyclicBarrier. CountDownLatch Java之CountDownLatc ...

  3. 进程隐藏与进程保护(SSDT Hook 实现)(二)

    文章目录:                   1. 引子 – Demo 实现效果: 2. 进程隐藏与进程保护概念: 3. SSDT Hook 框架搭建: 4. Ring0 实现进程隐藏: 5. Ri ...

  4. Pyhton 一行代码求Fibonacci第N项

    递归定义很简单,效率当然很低下,且极易超出栈空间大小. 这样做纯粹是为了体现python的语言表现力而已, 并没有任何实际意义. def fib(x): return fib(x-1) + fib(x ...

  5. Magento 多语言

    一: 1>进入后台选择如下: 2> 显示页面如下: 输入后台登陆的用户名和密码. 3>然后去Magento官网搜索一下 Magento Official Chinese Transl ...

  6. 50道经典的JAVA编程题(21-25)

    50道经典的JAVA编程题(21-25),明天早上java考试了,还是坚持做题吧...这题比老师的题好多了! [程序21]TestJieCheng.java题目:求1+2!+3!+...+20!的和1 ...

  7. 【Spark学习】Apache Spark项目简介

    引言:本文直接翻译自Spark官方网站首页 Lightning-fast cluster computing 从Spark官方网站给出的标题可以看出:Spark——像闪电一样快的集群计算 Apache ...

  8. Android Binder------ServiceManager启动分析

    ServiceManager启动分析   简述: ServiceManager是一个全局的manager.调用了Jni函数,实现addServicew getService checkService ...

  9. 只允许input框输入数字,输入其他的键的时候,直接不显示的方法

    function numInteger(){ if((event.keyCode>=48 && event.keyCode<=57)  || (event.keyCode& ...

  10. Linq知识小结

    Linq语法小结:有两种形式的语法可供我们在写Linq查询时使用,分别是“查询语法”.“方法语法”.1)先看个列子,有个直观认识     int[] arr = { 12, 2,45,34,23,18 ...