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());

参考资料

JS学习笔记3_函数表达式的更多相关文章

  1. JS学习笔记 (五) 函数进阶

    1.函数基础 1.1 函数的基本概念 函数是一段JavaScript代码,只被定义一次,但是可以被调用或者执行许多次.函数是一种对象,可以设置属性,或调用方法. 函数中的参数分为实参和形参.其中,形参 ...

  2. JS 学习笔记--7---正则表达式

    正则表达式中的内容很多,也很深,下面只是一些基本的知识点,练习中使用的浏览器是IE10,若有不当处请各位朋友指正,我会在第一时间修改错误之处. 匹配的概念:是包含的意思,不是相等的意思 1.正则表达式 ...

  3. js学习笔记19----getElementsByClassName函数封装

    js里面的getElementsByClassName()方法可通过某个class名获取到元素,在标准浏览器下可使用,在非标准浏览器下不可用.为了能够让这个方法兼容所有的浏览器,可以封装成如下函数: ...

  4. 10-Node.js学习笔记-异步函数

    异步函数 异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,是代码变得清晰明了 const fn = async()=>{} async fu ...

  5. JS 学习笔记--9---变量-作用域-内存相关

    JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已.由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的 ...

  6. WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)

    WebGL three.js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图: 时空隧道demo演示 Demo地址:https://nsytsqdtn.github.io/demo/sprite ...

  7. WebGL three.js学习笔记 法向量网格材质MeshNormalMaterial的介绍和创建360度全景天空盒的方法

    WebGL学习----Three.js学习笔记(5) 点击查看demo演示 Demo地址:https://nsytsqdtn.github.io/demo/360/360 简单网格材质 MeshNor ...

  8. WebGL three.js学习笔记 创建three.js代码的基本框架

    WebGL学习----Three.js学习笔记(1) webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的 ...

  9. vue.js 学习笔记3——TypeScript

    目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...

随机推荐

  1. Spring ConversionService 类型转换(一)Converter

    Spring ConversionService 类型转换(一)Converter Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.h ...

  2. mybatis高级映射-一对多

    订单(一)和(多)订单明细 数据库结构如下所示[演示数据,真实表比这复杂得多] order表 订单明细表 xml映射表 <resultMap type="xxx.order" ...

  3. rowspan和colspan的区别粗解

    rowspan和colspan是我们初学HTML表格中会在做一些特殊表格中遇到.其常在td中添加. rowspan的作用是指定纵向所跨越单元格的行数. 如下效果. colspan的作用是指定单元格横向 ...

  4. JS高级-String-正则表达式:

    1. String: 由多个字符组成的字符只读数组 vs 数组: 相同: 1. 下标, 2. .length, 3. 遍历, 4. .slice 不同: 类型不同!  API不通用 API: 所有字符 ...

  5. 日志分析工具、日志管理系统、syslog分析

    日志分析工具.日志管理系统.syslog分析 系统日志(Syslog)管理是几乎所有企业的重要需求.系统管理员将syslog看作是解决网络上系统日志支持的系统和设备性能问题的关键资源.人们往往低估了对 ...

  6. 爬虫模块之selenium模块

    一 模块的介绍 selenium模块最开始是一个自动化测试的工具,驱动浏览器完全模拟浏览器自动测试. from selenium import webdriver # 驱动浏览器 browser=we ...

  7. Hadoop3集群搭建之——虚拟机安装

    现在做的项目是个大数据报表系统,刚开始的时候,负责做Java方面的接口(项目前端为独立的Java web 系统,后端也是Java web的系统,前后端系统通过接口传输数据),后来领导觉得大家需要多元化 ...

  8. 2018.11.07 NOIP模拟 数独(模拟)

    传送门 sbsbsb签到题. 读题时间比写题时间长系列. 写一个checkcheckcheck函数来检验当前时间段第(i,j)(i,j)(i,j)号格子能否放入kkk就行了. 代码

  9. 2018.10.26 bzoj2721: [Violet 5]樱花(数论)

    传送门 推一波式子: 1x+1y=1n!\frac 1 x+\frac 1 y=\frac 1 {n!}x1​+y1​=n!1​ =>xy−x∗n!−y∗n!xy-x*n!-y*n!xy−x∗n ...

  10. Linux关机操作

    正确的关机流程为:sync > shutdown > reboot > halt 关机指令为:shutdown ,你可以man shutdown 来看一下帮助文档. 例如你可以运行如 ...