JS之函数表达式
度过一个愉快短暂的周末,又可以开始学习了!我爱学习,学习使人进步。今天学习函数表达式,着重学习下闭包函数。
函数表达式
可以在定义的函数声明之前调用它,但是不能在定义函数表达式之前调用它
- /**
- * 理解函数声明和函数表达式的区别,学习拉姆达(Lambda)表达式
- */
functionName(a);
aFuncton(a);//错误- function fuctionName(arg){};//函数声明
- var aFunction=function (arg) {};//函数表达式(匿名函数)
- /*
- 函数声明:在执行代码之前会先读取函数声明,函数声明可以放在调用它的语句后面。
Lambda表达式:创建匿名函数的一种方法,=>来表示
运算符右边的表达式对运算符左边指定的参数执行操作- */
var x=3,
fun=x=>{
return
x*x;};//lambda表达式
递归:在函数内部调用自己
- /**
- * 借用arguments.callee和使用函数命名表达式实现递归
- */
- //递归函数
- function factorial(num){
- if(num<=1){
- return 1;
- }else{
- return num*factorial(num-1);
- }
- };
- var anotherFactorial=factorial;
- factorial=null;
- alert(anotherFactorial(4));//出错,factorial值发生变化。
- //解决方案:1.非严格模式下
- function factorial(num){
- if(num<=1){
- return 1;
- }else{
- return num*arguments.callee(num-1);
- }
- };
- //2.命名函数表达式
- var factorial=(function f(num){
- if(num<=1){
- return 1;
- }else {
- return num * f(num - 1);
- }
- });
闭包:能够访问另一个函数作用域中的变量的函数。
作用域链:本质上是一个指向变量对象的指针列表
创建函数时,会创建一个预先包含全局变量对象的的作用域链,这个作用域链被保存在内部的[[Scope]]属性中,调用函数时创建一个执行环境,然后复制[[Scope]]属性中的对象构建起执行环境的作用域链,然后有一个函数的活动对象被创建并推入执行环境作用域链的前端。
在另一个函数内部定义的函数会将包含函数(即外部函数)的活动对象添加到它的作用域链中
- function createComparisonFunction(propertyName) {
- return function(object1,object2){
- var value1=object1[propertyName];
- var value2=object2[propertyName];
- if(value1<value2){return -1;}
- else if(value1>value2){return 1;}
- else{return 0;}
- };
- }
- //创建函数
- var compareNames=createComparisonFunction('name');
- //调用函数
- var result=compareNames({name:'赵云'},{name:'马超'});
- //解除对匿名函数的引用,以便释放内存
- compareNames=null;
作用域链可以想象成一个列表,里面的函数创建时候内部创建它,这个列表中,最上面的
上面的例子中,有两个作用域链,createComparisonFunction和匿名函数function(object1,object2)的作用域链分别是A和B。匿名函数从compareName()被返回后,B包含全局变量对象、createComparisonFunction函数的活动对象和匿名函数的活动对象的引用,createComparisonFunction函数执行完毕A被销毁,但是它的活动对象被B引用,虽然这样可以在全局环境中访问外部这个函数的变量了,但这个外部函数的活动对象已然存在。所以调用函数结束后要解除对匿名函数的引用。
- function a(){
- var result=[];
- for (var i=0;i<10;i++){
- result[i]=function ()
- { return i;};
- }
- }
上面的例子中,最后result数组中每个值都是10! 因为i是a函数活动对象中的变量,每个内部函数作用域链中都有a的活动对象,所以引用的是同一个i,a函数返回后i=10。
解决方案:使用立即执行函数
- 1 function a() {
- 2 var result = [];
- 3 for (var i = 0; i < 10; i++) {
- 4 result[i] = function (num) {
- 5 return function () {
- 6 return num;
- 7 }
- 8 }
- 9 return result;
- 10 }
- 11 }
在作用域中声明的变量,可能会被其他人不小心用同名的变量给覆盖掉,作用域链的特性,用匿名函数作为一个容器,容器内部可以访问外部的变量,而外部环境不能访问容器内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,相当于命名空间。
闭包中使用this对象
this对象是在运行时基于函数的执行环境绑定的:全局函数,this等于window,而当函数被最为某个对象的方法调用时,this就是那个对象。由于匿名环境具有全局性,它的this通常指向window.
- 1 var name='Window';
- 2 var object={
- 3 name:'object',
- 4 getName:function(){
- 5 return function () {
- 6 return this.name
- 7 }
- 8 }
- 9 };;
- 10 console.log(object.getName()) //Window
例子中getName方返回一个匿名函数,这个匿名函数返回this.name,调用内部匿名函数的时候,你不函数在搜索this和arguments两个变量时,只会搜索到活动对象为止。
解决方案:
- var name='Window';
- var object={
- name:'object',
- getName:function(){
- var that=this;
- return function () {
- return that.name;
- }
- }
- };
- console.log(object.getName());
闭包函数会导致内存泄露,在垃圾清理的引用计数模式中,如果有闭包函数作用域链中有html元素,则该元素的引用至少一直是1,因此它所占用的内存不会被回收,因此要吧该元素的赋值变量设为null;
模仿块级作用域:
(function(){})();//把函数声明转为函数表达式
立即调用了一个匿名函数
在一个由很多开发人员共同参与的大型应用程序中,过多的全局变量和函数容易导致命名冲突,通过创建私有作用域解决。
私有变量
任何函数中定义的变量,可以认为是私有变量。包括函数的参数,局部变量和函数内部定义跌其它函数。
访问私有变量方法:1构造函数中创建闭包
静态私有变量:利用原型。
重点:模块模式
对象字面量:实际是单例(只有一个实例的对象)。模块模式就是为单例创建私有变量和特权方法。
- 1 var singleton=function(){
- 2 //私有变量和私有函数
- 3 var privateVaribale=10;
- 4 function privateFunction(){
- 5 return false;
- 6 }
- 7 return{
- 8 publicProperty:true;
- 9 publicMethod:funciont(){
- 10 privateVaribale++;
- 11 return privateFunction();
- 12 }
- 13 };
- 14 }();
这个模块模式使用了一个返回对象的匿名函数。在这个匿名函数内部,首先定义了私有变量和函数,有一个对象字面量作为函数的值返回,因此它的公有方法有权访问私有变量和函数。从本质上来说,这个对象字面量定义的是单例的公共接口。这种模式在需要对单例进行某些初始化,同时又需要维护其私有变量时是非常有用的。
模块模式用来设计一个加载器什么的很有用,专门写一篇来分析。
JS之函数表达式的更多相关文章
- JavaScript--我发现,原来你是这样的JS:函数表达式和闭包
一.介绍 本次博客主要介绍函数表达式的内容,主要是闭包. 二.函数表达式 定义函数的两种方式:一个是函数声明,另一个就是函数表达式. //1.函数声明写法 function fn2(){ consol ...
- js中函数表达式和自执行函数表达式的用法总结
立即调用函数表达式 给函数体加大括号,在有变量声明的情形下,没有任何区别 但是,如果只是[自动执行]的情形下,就会不同 因为,一个匿名函数,不赋值或函数体不加小括号,是不能自动执行的 //以下情形并无 ...
- JS中函数表达式与函数声明的区别
hello,沐晴又来更新啦,今天呢,跟大家讲讲让人头疼的函数表达式和函数声明,反正我当初看那本高级程序的时候,是没怎么看太透,哈哈.我是个比较重基础的人,跟我一起探讨函数表达式和函数声明的世界吧. 首 ...
- javascript中函数声明和函数表达式的区别 分类: JavaScript 2015-05-07 21:41 897人阅读 评论(0) 收藏
1.js中函数表达式的定义 表达式(expression)JavaScript中的一个短语,javascript会将其计算(evaluate)出一个结果.程序中的常量是一个最简单的表达式.变量名也是一 ...
- js函数表达式和函数声明的区别
我们已经知道,在任意代码片段外部添加包装函数,可以将内部的变量和函数定义"隐 藏"起来,外部作用域无法访问包装函数内部的任何内容. 例如: var a = 2; function ...
- js立即调用的函数表达式
1.多种实现 // 下面2个括弧()都会立即执行 (function () { /* code */ } ()); // 推荐使用这个 (function () { /* code */ })(); ...
- JS中函数声明与函数表达式的不同
Js中的函数声明是指下面的形式: function functionName(){ } 这样的方式来声明一个函数,而函数表达式则是类似表达式那样来声明一个函数,如 var functionName ...
- [JS]深入理解JavaScript系列(4):立即调用的函数表达式
转自:汤姆大叔的博客 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行.在详细了解这个之前,我们来谈了解一下"自执行"这个叫法 ...
- js学习之函数声明与函数表达式区别[原创]
作为一名js初学者,与大家分享下.Javascript中有函数声明提升的功能,会优先编译函数声明部分.比如, ff(); function ff(){ alert("hello world. ...
随机推荐
- Java白皮书的关键术语
“白皮书”可以在http://www.oracle.com/technetwork/java/langenv-140151.html上找到. 1.简单性. 2.面向对象. 3.网络技能(Network ...
- ZXingObjC 64位 集成到自己的项目中(xcode 6.4)
参考 http://www.cocoachina.com/bbs/read.php?tid-280058-page-1.html 楼主发的DEMO中 ZXingObjC 支持64位 但是是以项目形 ...
- caffe源码阅读(一)convert_imageset.cpp注释
PS:本系列为本人初步学习caffe所记,由于理解尚浅,其中多有不足之处和错误之处,有待改正. 一.实现方法 首先,将文件名与它对应的标签用 std::pair 存储起来,其中first存储文件名,s ...
- MongoDB快速学习笔记
一,下载. XP系统,32位的下载地址: https://www.mongodb.org/dl/win32/i386 例:win32/mongodb-win32-i386-2.0.7.ziphttp: ...
- socket关联查询
反向代理服务器面对用户请求和后端服务器响应,需要将两者联系起来,于是就涉及到socket关联查询了. 代理服务器处理用户的请求和后端服务器的响应,并且这两方的请求和响应是相互对应的,因此对于代理接收到 ...
- 编程模式之装饰模式(Decorator)
装饰模式由四个角色组成:抽象组件角色,抽象装饰者角色,具体组件角色,具体装饰者角色. 抽象组件角色:给出一个抽象接口,以规范"准备接受附加功能"的对象. 抽象装饰者角色:持有一个组 ...
- 深入了解jQuery之整体架构
本文是在阅读了Aaron艾伦的jQuery源码解析(地址:http://www.imooc.com/learn/172)后的个人体会以及笔记.在这里感谢艾伦老师深入浅出的讲解!! 先来看看如何生成一个 ...
- 线程小demo
下午就手写了两个demo,整理了一下. #!/sur/bin/env python # -*- coding:utf-8 -*- __author__ = 'ganzl' import threadi ...
- 今天使用bootstrap中的tagsinput控件,碰到个小问题
我直接使用时,后台一直报Uncaught Can't add objects when itemValue option is not set错误, 代码如下: <div> <inp ...
- 一步一步了解Cocos2dx 3.0 正式版本开发环境搭建(Win32/Android)
cocos2d-x 3.0发布有一段时间了,作为一个初学者,我一直觉得cocos2d-x很坑.每个比较大的版本变动,都会有不一样的项目创建方式,每次的跨度都挺大…… 但是凭心而论,3.0RC版本开始 ...