函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
js
支持两种函数:一类是语言内部的函数(如eval()
),另外一类是本身建立的。javascript
在 JavaScript
函数内部声明的变量(使用 var)是局部变量,因此只能在函数内部访问它。(该变量的做用域是局部的)。java
您能够在不一样的函数中使用名称相同的局部变量,由于只有声明过该变量的函数才能识别出该变量。jquery
有以下四种调用js
函数的方式:编程
call()
和apply()
1. 当函数无明确返回值时,返回的值就是`undefined`。 2. 当函数有返回值时,返回值是什么就返回什么。
咱们能够经过使用 return
语句实现将函数返回调用它的地方。segmentfault
在使用 return
语句时,函数会中止执行,并返回指定的值。数组
函数一般会返回一个惟一值,那么这个值也多是另外一个函数:闭包
<script type="text/javascript"> //函数表达式 var box = function(){ var a=1; return function(){ alert(a++) } alert(a);//永远不会执行 } alert(box());//弹出"function(){alert(a++)}" </script>
在这里,咱们只需将返回值赋值给某个变量,而后就能够像使用通常函数那样调用它了:app
<script type="text/javascript"> var box = function(){ var a=1; return function(){ alert(++a) } } var newFunc = box(); newFunc();//2 </script>
若是想让返回的函数当即执行,亦可使用box()()
来执行这段代码。函数
ECMAScript
全部函数的参数都是按值传递的,言下之意就是参数不会按引用传递。学习
PS:若是存在按引用传递的话,那么函数里的那个变量将会是全局变量,在外部也能够访问。
(1)值类型:数值、布尔值、null、undefined。 (2)引用类型:对象、数组、函数。
引用类型值
:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针执行内存中的另外一个位置,由该位置保存对象;
function(){ return ‘hi’; //单独的匿名函数是没法运行的,就算能运行也没法调用,由于没有名字 }
这种匿名函数的用法在JQuery
中很是多。直接声明一个匿名函数,当即使用。用匿名函数的好处就是免得定义一个用一次就不用的函数,并且免了命名冲突的问题,js
中没有命名空间的概念,所以很容易函数名字冲突,一旦命名冲突以最后声明的为准。
在javascript
语言里任何匿名函数都是属于window
对象。在定义匿名函数时候它会返回本身的内存地址,若是此时有个变量接收了这个内存地址,那么匿名函数就能在程序里被使用了,由于匿名函数也是在全局执行环境构造时候定义和赋值,因此匿名函数的this
指向也是window
对象
(function(){ console.log(this === window);//true })();
经过自我执行来执行匿名函数:
//经过自我执行来执行匿名函数 <script type="text/javascript"> (function (){ // (匿名函数)();第一圆括号放匿名函数,第二个圆括号执行 alert('Lee'); })(); </script>
把匿名函数自我执行的返回值赋给变量:
//把匿名函数自我执行的返回值赋给变量 <script type="text/javascript"> var box = (function (){ alert('Lee'); })(); //弹出”Lee”; alert(box); //弹出 undefined </script> var box= (function () { return 'hi'; })(); console.log(box);//hi
自我执行匿名函数的传参:
//自我执行匿名函数的传参 <script type="text/javascript"> (function (age){ alert(age); })(100); //弹出100 </script>
var result = function (){ alert(2); }();
另外一种语法也可获得一样结果:
var result = (function () { console.log(2); })();
将函数返回值分配给变量:
var result = (function () { return 2; }());
js
建立动态函数: js
支持建立动态函数,动态函数必须用Function
对象来定义(Function是js
中的一个对象,是固定不变的,规定Function
对象的"F"必须大写,当是function
的时候,咱们知道是定义函数的时候所使用的一个关键字:function funName(x,y)
,当是Function
的时候(F大写的时候),咱们知道是js
中的对象)
建立动态函数的基本格式:var 变量名 = new Function("参数1","参数2","参数n","执行语句");
看下面的一段代码:
<script type="text/javascript"> var square = new Function ("x","y","var sum ; sum = x+y;return sum;"); alert("square(2,3)的结果是:"+square(2,3)); //square(2,3)的结果是:5 </script>
square
是动态建立的函数,在Function
对象后面的括号里的每一部份内容都必须是字符串形式的,也就是说都必须用引号(""或者是'')括起来
这段代码:
var square = new Function ("x","y","var sum ; sum = x+y;return sum;");
和下面这段代码:
//函数声明 function square (x,y){ var sum; sum = x+y; return sum; }
是一摸同样的,只不过一个是动态函数
,一个是静态函数
。
咱们为何要把代码分红一小段一小段的代码呢?,把一个字符串分红了若干个独立的字符串的优势就在于咱们能够经过修改其中的某些字符串来随时改变函数的做用。
回调就是一个函数的调用过程。那么就从理解这个调用过程开始吧。函数a有一个参数,这个参数是个函数b,当函数a执行完之后执行函数b。那么这个过程就叫回调。
其实中文也很好理解:回调,回调,就是回头调用的意思。函数a的事先干完,回头再调用函数b。
这里必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。
在jquery里的绝大多数效果函数都涉及到callback函数。jquery效果函数
例如:
<script type="text/javascript"> $("div").show(1000,function(){ //callback function }); </script>
这里的callback function
换成实例能够是:
<script type="text/javascript"> $("div").show(1000,function(){ console.log("hello world") }); </script>
Callback
其实是,当一个函数执行完后,现执行的那个函数就是所谓的callback
函数。怎么样?很好理解吧……
var arr = [1,2,3,4,5] var a =12; // 变量:自由的 arr.a= 5; //属性:属于一个对象 function show() //函数:自由的 { alert(‘a’); } arr.fn = function() //方法:属于一个对象 { alert(‘b’); }
其实方法就是函数,只不过方法是有所属的对象。
咱们所熟知的,将函数绑定到 click
事件
语法:
$(selector).click(function)
参数 | 描述 |
---|---|
function | 可选。规定当发生 click 事件时运行的函数. |
这种形式在jquery
中常常见到。它是将function
当作该方法的参数,向该方法添加一个事件处理函数。
全局函数与内置对象的属性或方法不是一个概念。全局函数它不属于任何一个内置对象。
JavaScript 中包含如下 7 个全局函数,用于完成一些经常使用的功能:
escape( )、eval( )、isFinite( )、isNaN( )、parseFloat( )、 parseInt( )、unescape( )。
function Class(){} Class.prototype={}; var item=new Class();
(function(){ //独立做用域 })();
所谓构造函数,就是经过这个函数生成一个新对象(object)。
<script type="text/javascript"> function Test(){//大写,以区分普通函数 this.x = 10; } var obj = new Test(); alert(obj.x); //弹出 10; </script>
可使用 new
运算符结合像 Object()
、Date()
和 Function()
这样的预约义的构造函数来建立对象并对其初始化。面向对象的编程其强有力的特征是定义自定义构造函数以建立脚本中使用的自定义对象的能力。建立了自定义的构造函数,这样就能够建立具备已定义属性的对象。下面是自定义函数的示例(注意 this
关键字的使用)。
function Circle (xPoint, yPoint, radius) { this.x = xPoint; // 圆心的 x 坐标。 this.y = yPoint; // 圆心的 y 坐标。 this.r = radius; // 圆的半径。 }
调用 Circle 构造函数时,给出圆心点的值和圆的半径(全部这些元素是彻底定义一个独特的圆对象所必需的)。结束时 Circle 对象包含三个属性。下面是如何例示 Circle
对象。
var aCircle = new Circle(5, 11, 99);
使用构造器函数的优势是,它能够根据参数来构造不一样的对象。 缺点是构造时每一个实例对象都会生成重复调用对象的方法,形成了内存的浪费。
<script type="text/javascript"> function Test(name){ this.occupation = "coder"; this.name = name; this.whoAreYou = function(){ return "I'm " + this.name + "and I'm a " + this.occupation; } } var obj = new Test('trigkit4');//利用同一个构造器建立不一样的对象 var obj2 = new Test('student'); obj.whoAreYou();//"I'm trigkit4 and I'm a corder" obj2.whoAreYou();//"I'm student and I'm a corder" </script>
依照惯例,咱们应该将构造器函数的首字母大写,以便显著地区别于通常的函数。
如下两种形式的定义函数方式是等价的。
<script type="text/javascript"> var test = function(){ alert("Hello World"); } alert(typeof(test));//output function </script>
这里明肯定义了一个变量test
,他的初始值被赋予了一个function
实体
<br/>
<script type="text/javascript"> function test(){ alert("Hello World"); } alert(typeof(test));//output function </script>
<br/>
看看下面这种定义式函数形式:
<script type="text/javascript"> function test(){ alert("Hello World"); }; test();//竟然输出Hello,很奇怪不是吗? function test(){ alert("Hello"); }; test();//正常滴输出了Hello </script>
很显然,第一个函数并无起到做用,很奇怪不是吗?咱们知道,javascript
解析引擎并非一行一行地执行代码,而是一段一段地执行代码。在同一段程序的分析执行中,定义式的函数语句会被优先执行,因此第一个定义的代码逻辑已经被第二个覆盖了,因此两次调用相同函数,只会执行第二个。
函数在js
中不只是一种语法,也是一个值。也就是说能够将函数赋值给变量,存储在对象的属性或数组的元素中,做为参数传入另外一个函数中。
函数的名字实际是看不见的,它仅仅是变量的名字,这个变量指代函数对象
<script type="text/javascript"> function square(x,y){ return x*y; } var s = square; //s和square指代同一个函数 square(2,3);//6 s(2,4);//8 </script>
除了能够将函数赋值给变量,一样能够将函数赋值给对象的属性,当函数做为对象的属性调用时,函数就称为方法
<script type="text/javascript"> var obj = {square:function(x,y){ //对象直接量 return x*y; }}; var ect = obj.square(2,3); </script>
每个函数都包含prototype属性,这个属性指向一个对象的引用,这个对象称为原型对象。
详见:javascript学习总结(五)原型和原型链
apply()
函数有两个参数:第一个参数是上下文,第二个参数是参数组成的数组。若是上下文是null,则使用全局对象代替。例如:
function.apply(this,[1,2,3])
call()
的第一个参数是上下文,后续是实例传入的参数序列,例如:
function.call(this,1,2,3);
这里的高阶函数可不是高数里的那个高阶函数,所谓高阶函数就是操做函数的函数,它接收一个或多个函数做为参数,并返回新函数
当函数被调用时,会获得一个免费奉送的参数数组,那就是arguments
数组。经过它,函数能够访问全部它被调用时传递给他的参数列表。这使得编写一个无需指定参数个数的函数成为可能。
<script type="text/javascript"> var sum = function(){ var i ,sum =0; for(i = 0;i<arguments.length;i+=1){ sum+=arguments[i]; } return sum; }; document.writeln(sum(4,5,23,13,35,46,-10));//116 </script>
在ECMAScript
中的参数在内部是用一个数组来表示的,函数接收到的始终都是这个数组,而不关心数组中包含哪些参数
function add(num1,num2){ num = num1 + num2; return num; } var result = 12,count = 20; alert(add(result,count));//32;命名的参数只提供便利,解析器不会验证命名参数
实际上,arguments
并非一个真正的数组,它只是一个类数组的对象,它拥有一个length
属性,但他缺乏全部数组的方法。另外,arguments
对象的长度是由传入的参数个数决定的,而不是由定义函数时的命名参数的个数决定的
函数在定义或者声明的时候,全部的参数都是形参,所以,咱们能够根据实际状况来命名参数,函数也只有在被调用时才会传入实参。而每一个函数在被调用时都会自动取得两个特殊变量:this 和 arguments
函数的递归,即一个函数在经过名字调用自身的状况下构成的:
经过使用argument.callee
代替函数名:
//arguments.callee是一个指向正在执行的函数的指针 <script> function factorial(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); } } </script>
最后附上一张前辈总结的思惟导图: