JS学习笔记3_函数表达式

来源:互联网 发布:java类的成员变量 编辑:程序博客网 时间:2024/05/18 15:05

JS学习笔记3_函数表达式

阅读(1,066) 评论(2JS2015-04-07

1.函数表达式与函数声明的区别

函数声明有“提升”(hoisting)的特性,而函数表达式没有。也就是说,函数声明会在加载代码时被预先加载到context中,而函数表达式只有在执行表达式语句时才会被加载

2.闭包

有权访问另一个函数作用域中的变量的函数。闭包可以访问另一个作用域中的变量,因此闭包得到的变量值是最终值,而不是该变量在某一时刻的值,有一个很经典的例子:

function createFuns(){  var result = new Array();  for(var i = 0;i < 10;i++){    result[i] = function(){      return i;    };    /*    result[i] = function(arg){      return function(){        return arg;      }    }(i);//此处匿名函数立即执行的()可以省略,因为function在等号右边出现,不存在歧义(一般形式是(function(){})())    */  }  return result;}

createFuns函数返回一组函数,这些函数执行结果都是10(闭包得到的变量值是最终值),但注释中的方式返回函数的执行结果就是i的当前值,因为是值传递

3.函数表达式中的this

内部函数无法直接访问外部函数中的this和arguments对象,因为内部函数在搜索这两个变量时,只会搜索到其活动对象为止

P.S.活动对象是作用域链的实体,作用域链是抽象概念,而活动对象就是这个概念的具体实现。其实作用域链映射到代码里就是变量对象链条,又扯出了变量对象,不用怕,一点都不复杂:

执行环境(context)中定义的所有变量和函数都保存在变量对象中,如果执行环境是一个函数,那就把函数的活动对象当作变量对象,并作为变量对象链的一环,也就是作用域链的一环。

一开始函数的活动对象只有一个属性——arguments对象,每在函数内部声明一个自定义属性,就给该函数的活动对象添加一个属性。。。

嗯,扯了这么多,其实就一句话:this就是活动对象/变量对象的引用

如果还不大明白,请参考前辈的博文,顺便推荐这位前辈的其它博文,关于js的都很不错

4.重复声明变量

不会引起语法错误,会自动忽略多余的声明,但声明同时的初始化操作被执行,例如:

var x = 1;var x = 2;//var声明被忽略,所以不报错,但赋值会被执行alert(x);//2

5.实现块级作用域的思路

声明一个匿名函数并立即调用,那么匿名函数内部就是块级作用域。具体实现:

(function(){/*块级作用域*/})();

注意:需要用圆括号来消除函数表达式与函数声明的歧义(从解释器的角度看就是这样),因为函数声明后面不能直接跟圆括号,而函数表达式可以。

P.S.示例中的代码只是一种实现IIFE的方式,还有几种,具体请参考[javascript]IIFE立即执行的函数表达式,这篇博文给出了详细的对比

6.私有变量

函数内部用var或者function声明的变量是私有变量。(实例无法直接访问,可以通过定义公有函数来提供访问接口)

而用this.attr = value;方式声明的变量是公有变量。(实例可以直接访问)

7.闭包、匿名函数、内部函数、内部匿名函数的区别

  • 闭包:有权访问另一个函数作用域中的变量的函数

  • 匿名函数:没有名字的函数表达式

  • 内部函数:在函数内部声明的函数,也就是闭包

  • 内部匿名函数:在函数内部声明的匿名函数,当然,也是闭包

P.S.滥用闭包可能会占用大量内存,闭包之所以能够访问外层函数作用域中的变量,是因为闭包的活动对象持有外层函数活动对象的引用

只有在闭包被销毁后,外层函数中的变量才能被销毁,不能及时销毁,所以可能占用大量内存

8.执行函数的整个过程

  1. 创建执行环境context,context有内部属性[[Scope]]

  2. 更新作用域链ScopeChain

  3. 创建活动对象

  4. 初始化活动对象的this, arguments, 形参等各个属性

  5. 执行函数体

  6. 销毁活动对象(存在闭包时无法销毁)

  7. 更新作用域链

9.js单例模式与模块模式

  • 单例模式:创建只有一个实例的对象的一种模式,说白了,模式就是方法,设计模式就是前辈总结出来的好方法。js中实现单例模式尤其简单:

    var singleton = {attr1: value1, attr2: value2};

    没错,就是对象字面量,其实就是创建了匿名对象,不知道构造函数的名字,当然无法创建第2个实例了

  • 模块模式:道格拉斯提出的用来增强单例的方法,可以给单例添加私有属性和公有属性(有时候也叫特权属性,表示有权修改私有属性的属性),例如:

    var singleton = function(){  //私有属性  var privateStr = 'secret';  function addPrefix(){    privateStr = 'this is my ' + privateStr;  }  //公有属性(特权属性)  return{//返回一个匿名对象    getStr : function(){      addPrefix();      return privateStr;    }  };}();//又是匿名函数立即执行alert(singleton.getStr());

P.S.如果不需要单例,只要保护私有属性的话,可以这样做:

function Cat(){  //私有属性  var privateStr = 'secret';  function addPrefix(){    privateStr = 'this is my ' + privateStr;  }  //公有属性(特权属性)  this.getStr = function(){    addPrefix();    return privateStr;  }}var obj = new Cat();alert(obj.getStr());
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 俩月的宝宝便秘怎么办 宝宝6天没大便怎么办 新生儿3天不大便怎么办 50天宝宝几天没有大便怎么办 宝宝一吃奶就拉怎么办 2个月宝宝不拉屎怎么办 吃苹果呛到气管怎么办 三个月宝宝五天没拉大便了怎么办 三个月的宝宝五天不大便怎么办 十天婴儿不大便怎么办 宝宝断奶不喝牛奶怎么办 宝宝喝羊奶大便干燥怎么办 4个月宝宝睡眠少怎么办 8个月婴儿不吃奶粉怎么办 满月的宝宝黄疸高怎么办 刚满月的宝宝黄疸高怎么办 换奶粉孩子不喝怎么办 宝宝整夜哭闹不睡觉怎么办 满月宝宝整夜不睡觉怎么办 6个半月宝宝一喂粥就哭怎么办 宝宝敷鸡蛋白过敏怎么办 七个月宝宝不吃米糊怎么办 涨奶引起的发烧怎么办 8个月宝宝积食怎么办 宝宝吃奶一会就睡了怎么办 宝宝喝凉酸奶拉肚子怎么办 宝宝戒奶不吃奶粉怎么办 三个月大婴儿不吃奶粉怎么办 三个月大的婴儿不吃奶粉怎么办 40天宝宝肚脐凸怎么办 6个月婴儿消化不好怎么办 2个月婴儿消化不好怎么办 10月婴儿不吃饭怎么办 9个月宝宝不吃饭怎么办 十个多月的宝宝便秘怎么办 十个多月宝宝便秘怎么办 8个月宝宝过敏怎么办 宝宝二十个月便秘怎么办 7个月宝宝便秘拉不出怎么办 二十六个月宝宝便秘怎么办 八个月宝宝吃鸡蛋过敏怎么办