资讯专栏INFORMATION COLUMN

js函数的那些事(一)

Bamboy / 2708人阅读

摘要:不一定有函数名,所以有匿名函数表达式和命名函数表达式。引用的是函数据以执行的环境对象。匿名函数引用函数作用域内的活动变量时,已经等于了,所以每个函数返回的都是。

文章融合了《JavaScript高级程序设计》的知识,和这几天在segmentfault上的文章的知识点。属于整合类文章吧。

函数简介

函数声明和函数表达式

this和argument

闭包

函数简介

函数实际上是对象,所以函数名实际上是指向函数对象的指针,那么一个函数可能有多个名字。

function sum(num1,num2){
    retrun num1+num2;
}
alert(sum(10,10));  //20

var anotherSum=sum;  //将sum的值赋给了anotherSum,此时它们都指向同一个函数。
alert(anotherSum(10,10));  //20

sum=null;    //将sum设置为null,使它与函数“断绝关系”
alert(anotherSum(10,10));  //20 ,仍然可以正常调用。

没有重载
函数重载:函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。js没有重载的概念,所以如果声明了两个同名函数,则后面的函数会覆盖前面的函数。

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

    //把一个函数传递给另一个函数的例子
    function callFunction(someFunction,someArgument){
        return someFuction(someArgument);
    }
    function add10(num){
        return num+10;
    }
    var result=callFunction(add10,10);  //要访问函数的指针而不执行函数的     
    话,要去掉函数名后的圆括号。
    alert(result);  //20
函数声明和函数表达式

定义函数方法:

首先是函数声明: function functionName(){}必须有函数名。
然后是函数表达式,比如:

 var sum = function(num1,num2){
        retrun num1+num2;
    };                      //函数末尾有分号,就像声明其他变量时一样。

不一定有函数名,所以有匿名函数表达式和命名函数表达式。不过,对函数命名后,一是在函数体内会表达得更清晰,二则是在调试的时候要方便很多。

区别:
函数声明可以在定义前调用(函数声明提升),函数表达式不可以(和其他表达式一样,使用前必须要赋值)。
函数声明只是让浏览器知道有这样一个函数了,不会运行。浏览器遇到函数表达式会运行。
如果不做函数声明的话,一般就不希望被重复调用,即很大可能就当做立即执行函数使用。
如果函数体作为表达式的一部分,那它是函数表达式,否则为函数声明。

this和arguments

在函数内部有两个特殊的对象:arguments和this。
arguments是一个类数组对象,包含传入函数的所有参数。主要作用就是保存函数参数。
arguments有一个callee属性,该属性是一个指针,指向拥有arguments对象的函数。
例子:

function factorial(num){
    if(num<=1){
      return 1;
    }else{
      return num*factorial(num-1);
    }
}

在函数factorial中调用了他本身,但是如果要是将函数赋值给别的变量,那就不能正常运行了。如果是下面的代码:

 function factorial(num){
        if(num<=1){
          return 1;
        }else{
          return num*arguments.callee(num-1);
        }
    }

这样,不管调用函数时使用什么名字,都可以保证正常完成递归调用。
this:
this引用的是函数据以执行的环境对象。

函数调用模式时,this指向window。

方法调用模式时,this指向方法所在对象。

wiondow.color="red";
var o={color:"blue"};
function sayColor(){
     alert(this.color);
}
sayColor();    //"red" 
o.sayColor=sayColor;
o.saColor();   //"blue"

构造函数模式时,this指向新生成的实例。

    function Aaa(name){
      this.name= name;
      this.getName=function(){
        console.log(this.name)
      }
    }
    var a = new Aaa("kitty");
    a.getName()        //  "kitty"
    var b = new Aaa("bobo");
    b.getName()        //  "bobo"

apply/call调用模式时,this指向apply/call方法中的第一个参数。

   var list1 = {name:"andy"}
   var list2 = {name:"peter"}
   
   function d(){
     console.log(this.name)
   }
   d.call(list1)     //  "andy" 
   d.call(list2)     //  "peter"
  

闭包

概念:是指有权访问另一个函数作用域中变量的函数。
创建闭包方法:在一个函数内部创建另一个函数。

特征:

可以访问外部函数的变量。

比较占内存。因为闭包会携带包含他的函数的作用域,在闭包被销毁后外部函数的活动变量才会被销毁。
(ps:关于活动变量知乎上这个问题的第二个答案写的非常非常好!)

闭包只能取得外部函数中任何变量的最后一个值。所以要注意闭包和循环的使用:

   function foo(){
   var result=new Array();
   for (var i=0;i<10;i++){
       result[i]=function(){
           return i;
       };
   }
   return result;

}
返回了一个函数数组,每个函数都返回10。因为运行foo()函数的顺序是这样的:先运行foo()函数除了匿名函数之外的部分,完成后,再运行匿名函数。这时候for循环已经完成了,i变成了10。匿名函数引用foo()函数作用域内的活动变量i时,i已经等于10了,所以每个函数返回的都是10。

改进:

function foo(){
        var result=new Array();
        for (var i=0;i<10;i++){
            result[i]=function(num){
                return function(){
                  return num;
                };
            }(i);
        }
        return result;
    }

模仿块级作用域的方法。在调用外部的匿名函数时,传入参数i,变量i的值赋给num,在外部匿名函数内部的闭包,访问的是numresult数组的每个函数都有自己num变量的一个副本,就可以返回各自不同的值

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86276.html

相关文章

  • JS异步那些 (基础知识)

    摘要:异步那些事一基础知识异步那些事二分布式事件异步那些事三异步那些事四异步那些事五异步脚本加载事件概念异步回调首先了讲讲中两个方法和定义和用法方法用于在指定的毫秒数后调用函数或计算表达式。功能在事件循环的下一次循环中调用回调函数。 JS异步那些事 一 (基础知识)JS异步那些事 二 (分布式事件)JS异步那些事 三 (Promise)JS异步那些事 四(HTML 5 Web Workers...

    李涛 评论0 收藏0
  • JS异步那些 三 (Promise)

    摘要:异常处理异常处理一直是回调的难题,而提供了非常方便的方法在一次调用中,任何的环节发生,都可以在最终的中捕获到错误处理基本的小结具体的很多的用法可以参考阮一峰的入门教程,还有就是上面提到的电子书。 JS异步那些事 一 (基础知识)JS异步那些事 二 (分布式事件)JS异步那些事 三 (Promise)JS异步那些事 四(HTML 5 Web Workers)JS异步那些事 五 (异步脚本...

    wenzi 评论0 收藏0
  • JavaScript模块化开发那些

    摘要:模块化开发在编程开发中是一个非常重要的概念,一个优秀的模块化项目的后期维护成本可以大大降低。本文主要介绍模块化开发的那些事,文中通过一个小故事比较直观地阐述了模块化开发的过程。每个模块都由一个名为的函数创建。原文出处模块化开发的那些事 模块化开发在编程开发中是一个非常重要的概念,一个优秀的模块化项目的后期维护成本可以大大降低。本文主要介绍JavaScript模块化开发的那些事,文中通过...

    jzzlee 评论0 收藏0
  • JS基础】原型对象那些(二)

    摘要:只是构造函数上的一个属性,它是一个指针,指向原型对象,并不表示就是原型对象。在上一个例子中,就是一个对象,这个对象可以说是原生构造函数的实例,所以也是一个对象,所以它也有属性,不过它的指向也就是原型链的顶端,再往上就没有了。 上一篇讲了①原型对象是什么;②__proto__、prototype、constructor的关系;③原型对象的作用;④原型对象带来的一些需要注意的问题; 没理解...

    yanbingyun1990 评论0 收藏0
  • JS基础】原型对象那些

    摘要:通过同一个构造函数实例化的多个实例对象具有同一个原型对象。所以当给原型对象赋值一个新对象时,切记将原型对象的指回原构造函数以上就是本次分享的内容,关于原型对象的其他知识,下一篇基础原型对象的那些事二会讲到。 谈起js的基础,绕不过去的坎就是:原型链、作用域链、this(em...好吧,还有闭包),今天总结一下关于原型对象的一些知识,供自己和大家复习。 概念理解 什么是原型对象呢?有以下...

    edgardeng 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<