JavaScript 属于解释型语言,JavaScript 的执行分为:解释和执行两个阶段,这两个阶段所做的事并不一样:

解释阶段:

  • 词法分析
  • 语法分析
  • 作用域规则确定

执行阶段:

  • 创建执行上下文
  • 执行函数代码
  • 垃圾回收

Hoisting--提升

Hoisting的发生范围是函数作用域(function-local scope)。在函数内var定义的变量和函数声名会被提升到该函数作用域的上面。function内的提升的顺序所下:

  1. this, arguments
  2. 形参 formal parameters
  3. 函数声名 function declarations
  4. 变量声名 variable declarations

举例:

var a = 1;

function test(){
if(!a){
var a = 5;
}
console.log(a);
} test();
//打印出5这

这是因为当解析器读到if语句时,发现有一个变量声名和定义:var a = 5;于是解析器就把这个变量的声名:var a;提到当前作用域的顶部。上面的代码最后执行是其实是这样的

var a = 1;

function test(){
var a;
if(!a){
a = 5;
}
console.log(a);
} test();

 如果想打印出1的话,需要用let来定义块级变量: let a =5;或者把var a = 5放到一个立即执行函数里。

再举一个函数提升的例子

function test(a){
if(!a){
var a = 5;
}
function a(){}//function declaration
console.log(a);
} test(0);
//打印出function a(){}

  执行的实际代码如下

function test(a){
function a(){}
var a;
if(!a){
a = 5;
} console.log(a);
} test(0);
//打印出function a(){}

  如果代码做以下修改

function test(a){
if(a){
var a = 5;
}
function a(){}
console.log(a);
} test(0);
//打印出5

  因为a被重新赋值了。

function test(a){
function a(){}
var a;
if(a){
a = 5;
}
console.log(a);
} test(0);
// if(a)一直是 true,打印出5

  

声名变量var a,只是让解释器知道有这个a的存在,a到底是什么,就需要对变量进行定义:a=5。如果再给a赋值:a = function(){},那a又被定义为了函数。a到底是什么是由定义来决定的。定义的是什么,输出的就是什么。不为因为再次的声名而改变。如果用函数表达式来定义函数,会出现什么情况:

function test(){
b();
var b = function (){}
}
test()
//会报错“undefined is not a function”

  函数表达式时,只用变量名被提升,它定义的函数体依然留在原处。执行的代码是这样的

function test(){
var b;
b();
b = function (){}
}
test()

 只对b做了声名,而没有定义,所以执行到b()会报错。

Scoping--作用域

ES6之前只有函数作用域。ES6加入块级作用域。用let声名的变量是块作用域内有效,用var声名的变量在函数作用域与块作用域里有效。

作用域链

作用域内取值是从创建该函数的位置取值,而不是从调用该函数的位置取值。

https://yq.aliyun.com/articles/693736

Execution Context 执行上下文

执行上下文是在执行过程中产生的。

https://juejin.im/post/59e85eebf265da430d571f89?spm=a2c4e.11153940.blogcont685883.21.727f127e0QVeWU

作用域和执行上下文之间最大的区别是:
执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变

IIFE(Immediately Invoked Function Expression)

形式有多种:

(function(){ cosole.log(1); })()

(function(){ console.log(1);}())

+function(){console.log(1);}()

!function(){console.log(1);}()

void function(){console.log(1);}()

这样写是编译不过去的:function(){console.log(1);}()

顾名思义,immediately invoked function expression,是被解析成为一个函数表达式,然后自执行。

立即调用函数有个超强的用法,模块模式,如下

var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function(val){
i = val;
},
increment: function(){
return ++i;
}
}
}());
counter.get();//0
counter.set(3);
counter.increment();//4
counter.increment();//5

  想要扩展counter的方法:

var counter = (function(c){
c.ext= function (){
console.log('extend');
}
return c;
}(counter || {}));
counter.ext();

  

refer: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.htm

https://yuiblog.com/blog/2007/06/12/module-pattern/

http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

http://www.cnblogs.com/TomXu/archive/2011/12/30/2288372.htmll

javascript的几个知识点scoping, hoisting, IIFE的更多相关文章

  1. 理解 JavaScript Scoping & Hoisting(二)

    理解 JavaScript Scoping & Hoisting(二) 转自:http://www.jb51.net/article/75090.htm 这篇文章主要介绍了理解 JavaScr ...

  2. JavaScript算法与数据结构知识点记录

    JavaScript算法与数据结构知识点记录 zhanweifu

  3. JavaScript必须了解的知识点总结。

    整理的知识点不全面但是很实用. 主要分三块: (1)JS代码预解析原理(包括三个段落): (2)函数相关(包括 函数传参,带参数函数的调用方式,闭包): (3)面向对象(包括 对象创建.原型链,数据类 ...

  4. JavaScript必须了解的知识点总结【转】

    整理的知识点不全面但是很实用. 主要分三块: (1)JS代码预解析原理(包括三个段落): (2)函数相关(包括 函数传参,带参数函数的调用方式,闭包): (3)面向对象(包括 对象创建.原型链,数据类 ...

  5. javascript 关于闭包的知识点

    javascript 关于闭包的认识 概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制. 所以要大致搞清三个东西:函数对象(function object ...

  6. 私人定制javascript中对象小知识点(Only For Me)

    废话不多讲,先上笑话,然后再,.看懂这个的说明你的节操已经不再了. 晚饭后去理发店理发...割了吧...老板问我怎么剪,我悠悠的来一句往帅了剪...高潮往往令人想不到....旁边一在焗油烫头发的大妈说 ...

  7. 读《javascript语法精粹》知识点总结

    昨天泡了大半天的读书馆,一口气看完了<javascript语法精粹>这本书,总体来说这本书还是写的不错,难怪那么多的推荐.<javascript语法精粹>主要是归纳与总结了ja ...

  8. 漫谈JavaScript中的提升机制(Hoisting)

    前言 刚接触到JavaScript的时候,便知道JavaScript是按顺序执行的,是如浏览器的解析DOM树一样的流程,解析DOM结构的时候,如果遇到JS脚本或者外联脚本便会停止解析,继续下载脚本之后 ...

  9. JavaScript学习笔记——对象知识点

    javascript对象的遍历.内存分布和封装特性 一.javascript对象遍历 1.javascript属性访问 对象.属性 对象[属性] //字符串格式 //javascript属性的访问方法 ...

随机推荐

  1. 理解JS深拷贝

    前言: JS的拷贝(copy),之所以分为深浅两种形式,是因为JS变量的类型存在premitive(字面量)与reference(引用)两种区别.当然,大多数编程语言都存在这种特性. 众所周知,内存包 ...

  2. 虚拟机——虚拟机VMware Workstation 的.vmdk格式与VirtualBox 的.vdi格式相互转换

    啦啦啦~~~ 由于现在Vmware Workstation的越来越普及,让很多小伙伴不知道怎么把以前用的VirtualBox虚拟机vdi格式转换成vmdk格式,下面我们就来转换一下吧... 第一步:找 ...

  3. 用Volume在主机和Docker容器文件传输

    1.使用Volume在主机和容器之间传输文件. 在官方文档中可以看到使用如下命令即可创建一个volume: Create a volume: $ docker volume create my-vol ...

  4. Linux环境上部署Flask

    [该文章只涉及个人部署的简单流程,读者可通过其它途径了解详细部署流程] 依个人部署项目可预先安装好需要的环境,这里已提前安装好LNMP环境 1.安装Python环境 安装virtualenv环境 配置 ...

  5. HBase指定大量列集合的场景下并发拉取数据时卡住的问题排查

    最近遇到一例,HBase 指定大量列集合的场景下,并发拉取数据,应用卡住不响应的情形.记录一下. 问题背景 退款导出中,为了获取商品规格编码,需要从 HBase 表 T 里拉取对应的数据. T 对商品 ...

  6. kibana查询语法 使用教程

    1. 使用双引号包起来作为一个短语搜索: "like Gecko" 2. ? 匹配单个字符; * 匹配0到多个字符 例如:kiba?a, el*search ? * 不能用作第一个 ...

  7. Linux Spi驱动移植小结

    2012-01-07 22:21:29 效果图: 理论学习后,主要是linux中spi子系统设备框架的了解后,主控制器与设备分离的思想,那么我要开始动手了. 1,  make menuconfig添加 ...

  8. Java8过滤器(Filter)

    1.在Java之前对List进行过滤的方式 public class BeforeJava8 { public static void main(String[] args) { List<Pe ...

  9. mybatis的collection查询问题以及使用原生解决方案的结果

    之前在springboot+mybatis环境的坑和sql语句简化技巧的第2点提到,数据库的一对多查询可以一次查询多级数据,并且把拿到的数据按id聚合,使父级表和子级表都有数据. 但是这种查询,必然要 ...

  10. Linux的文件系统

    根文件系统(rootfs): root filesystem LSB, FHS: (FileSystem Heirache Standard) /etc, /usr, /var, /root, /ho ...