javaScript基础:函数
2016-06-24 07:03
405 查看
一、函数简介
函数是定义一次但却可以调用或执行任意多次的一段JS代码。
函数有时会有参数,即函数被调用时指定了值的局部变量。
函数常常使用这些参数来计算一个返回值,这个值也成为函数调用表达式的值。
二、函数的使用
1.函数的声明与调用
2.函数中的argument对象
ECMAScript函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上,函数体内可以通过arguments对象来接收传递进来的参数。
arguments是一个类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数。
注意:函数声明时若没有指定形参,调用时也可以传递实参,只是这时候要通过argument来拿到参数。
arguments这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
3.函数中的this对象
函数内部另一个特殊对象是this,其行为与Java和C#中的this大致相似。
换句话说,this引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域。函数内的this指的就是函数的调用者。
PS:当在全局作用域中调用函数时,this对象引用的就是window
三、匿名函数
1.匿名函数的创建
2.匿名函数的调用
ps:函数里边套函数其实就是闭包;
四、闭包
1.什么是闭包?
闭包是指有权访问另一个函数作用域中的变量的函数 ,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
有一个函数A, 函数A内部的有一个局部变量a;
有一个函数B。
函数B在函数A的内部。函数B有权访问变量a;
函数B就是一个闭包。
闭包的优点 可以把局部变量驻留在内存中 ,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。
闭包的缺点:由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。
举例:闭包将局部变量驻留在内存中
2.循环里的闭包
解决方法一:
解决方法二:
3.闭包里的this指向
在闭包中使用this对象也可能会导致一些问题,this对象是在运行时基于函数的执行环境绑定的,如果this在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window,因为闭包并不属于这个对象的属性或方法。
解决方法一:
函数是定义一次但却可以调用或执行任意多次的一段JS代码。
函数有时会有参数,即函数被调用时指定了值的局部变量。
函数常常使用这些参数来计算一个返回值,这个值也成为函数调用表达式的值。
二、函数的使用
1.函数的声明与调用
function box() { //没有参数的函数 alert('只有函数被调用,我才会被之执行'); } box();//函数调用
function box(name, age) { //带参的函数 alert('你的姓名:'+name+',年龄:'+age); } box('李炎恢',28);//函数调用,并传参注意:ECMAScript中的函数,没有像其他高级语言那种函数重载功能。 只要函数名一样就是一个函数,不会因为是否传参数而成为两个不同的函数。
2.函数中的argument对象
ECMAScript函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上,函数体内可以通过arguments对象来接收传递进来的参数。
arguments是一个类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数。
function box() { var sum = 0; if (arguments.length == 0) return sum; //如果没有参数,退出 //如果有,就累加 for(var i = 0;i < arguments.length; i++) { sum = sum + arguments[i]; } //返回累加结果 return sum; alert(box(5,9,12));//调用函数,并传递参数,可以传递任意个参数
注意:函数声明时若没有指定形参,调用时也可以传递实参,只是这时候要通过argument来拿到参数。
arguments这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
function box(num) { if (num <= 1) { return 1; } else { return num * arguments.callee(num-1);//使用 callee 来执行自身argument.callee(num-1)就相当于box(num-1) } }
3.函数中的this对象
函数内部另一个特殊对象是this,其行为与Java和C#中的this大致相似。
换句话说,this引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域。函数内的this指的就是函数的调用者。
PS:当在全局作用域中调用函数时,this对象引用的就是window
window.color = '红色的'; var box = { color : '蓝色的' }; function sayColor() { alert(this.color); } sayColor();//此时函数中的this是window对象 box.sayColor = sayColor; box.sayColor();//此时函数中的this是box对象
三、匿名函数
1.匿名函数的创建
//没有函数名的函数叫做匿名函数 //匿名函数会报错 function () { return 'lee'; }
2.匿名函数的调用
//通过表达式自我执行 (function (){//封装成表达式 alert('wang'); })();//()表示执行函数并传参3.匿名函数作为函数的返回值
var box = function (){//将匿名函数赋值给变量 return function(){//将匿名函数作为函数的表达式返回 return 'lee'; } }; var box2 = box();//此时box2 = function (){return 'lee';}; alert(box2());//弹出提示框lee;注意区别下边这种写法:
var box = (function (){//将匿名函数的返回值赋值给变量 return function (){//匿名函数作为函数的返回值 return 'lee'; } })(); alert(box());//此时box = function (){return 'lee';};
ps:函数里边套函数其实就是闭包;
四、闭包
1.什么是闭包?
闭包是指有权访问另一个函数作用域中的变量的函数 ,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
有一个函数A, 函数A内部的有一个局部变量a;
有一个函数B。
函数B在函数A的内部。函数B有权访问变量a;
函数B就是一个闭包。
闭包的优点 可以把局部变量驻留在内存中 ,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。
闭包的缺点:由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。
举例:闭包将局部变量驻留在内存中
var box = function (){ var num = 100; //创建一个闭包 return function (){ //访问函数box的局部变量,并将变量驻留在内存里 num ++; return num; } }; var box1 = box();//正常情况下方法执行完,num变量就会被释放掉。因为闭包的存在它会驻留在内存内。 alert(box1());//101 alert(box1());//102PS:如果再次调用box();那么num的值又会等于100.相当于重新赋值。
2.循环里的闭包
var box = function (){ var arr = []; //变量i是box内的局部变量 //匿名函数会使局部变量驻留在内存中。 for(var i = 0;i<5; i++){ //数组的每个元素都是一个函数,函数的返回值都是变量i; // 函数没有自我执行。只是将函数对象保存在数组内成为数组的元素。当调用这个函数时才会返回i的值。 arr[i] = function (){ return i; }; } return arr; }; var box1 = box();//box1是一个包含5个函数元素的数组. alert(box1); for(var i = 0;i<5;i++){ var num = box1[i]();//数组元素是函数,执行这个函数返回变量i的值。但此时i的值已经是5; alert(num);//返回的结果都是5; }PS:如果了解block的话,会发现闭包跟block很相似,都是一个代码片段,这个代码片段实质就是存储一个"方法",在需要的时候调用即可。
//void (^myBlock)(void)是一个名为myBlock的变量,但这个变量存储的是一个代码片段 //第一个void为返回值 //第二个void为参数 void (^block)(void)=^(){ //执行的代码 }; myBlock();//block调用 ()号内为传递的参数myBlock()整体就是返回值。可以发现跟方法的调用太相似 /* ^(){ //执行的代码 }; 相当于闭包 function (){ return i; } */
解决方法一:
arr[i] = (function (){//让内部函数立即执行,把执行结果存入数组内,这样数组内存的就不是函数而是函数的返回值 return i; })();
解决方法二:
var box = function (){ var arr = []; for(var i = 0;i<5; i++){ //在匿名函数内部再套一个匿名函数,将第一个匿名函数执行,并将i的值作为参数传递进去,赋值给num变量。num = i; arr[i] = function (num){ //num也是一个局部变量。 //num被第二个匿名函数访问,驻留在内存中 需要注意的是数组每个元素的存的是不同的函数对象,函数对象不同,num也不同 //也就是在执行过程中会产生5个num变量,他们分别被赋值为0,1,2,3,4后就没有在被访问。所以放第二个匿名函数被调用时他们的值就分别是0,1,2,3,4 return function (){ return num; }; }(i); } return arr; }; var box1 = box(); alert(box1); for(var i = 0;i<5;i++){ var box2 = box1[i](); alert(box2); }
3.闭包里的this指向
在闭包中使用this对象也可能会导致一些问题,this对象是在运行时基于函数的执行环境绑定的,如果this在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window,因为闭包并不属于这个对象的属性或方法。
var color = 'green'; var box = { color : 'red', run : function (){ return function (){ //闭包不属于box,里面的this指向window //这里的this指向的是window return this.color; } } }; alert(this.color);//green this指向window alert(box.run()());//green 闭包里的this同样指向window;
解决方法一:
//对象冒充: var box2 = box.run();//拿到这个闭包函数 alert(box2.call(box));//red this指向的是box对象。对象冒充解决方法二:
var color = 'green'; var box = { color : 'red', run : function (){ //这里的this指向的是box; var that = this;//拿到这个this对象 return function (){ //闭包不属于box,里面的this指向window。 //这里的this指向的是window return that.color;//返回that对象的color属性 } } }; alert(box.run()());//red
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 最后一次说说闭包
- Ajax
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法
- Redux系列02:一个炒鸡简单的react+redux例子
- JavaScript 各种遍历方式详解
- call/apply/bind 的理解与实例分享