JS 函数作用域及变量提升那些事!
虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~
这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~
主要参考书籍:
《你不知道的JavaScript(上卷)》第一部分
《JavaScript高级程序设计》第四章 4.2 执行环境与作用域
理解要点:
1. js其实是一门编译语言,代码的执行分为两个阶段:(《你不知道的JavaScript(上卷)》)
a.编译阶段
b.执行阶段
2. 作用域嵌套:
在当前作用域中无法找到某个变量时,引擎就会在外层嵌套中继续查找,直到找到该变量,或是抵达最外层作用域为止。(《你不知道的JavaScript(上卷)》)
3. 包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。变量及函数声明的提升也是在这个阶段。
注意:(1)变量及函数声明的提升只是提升“声明”,并不会提升“赋值”,赋值是在函数执行阶段完成的。
(2)函数表达式不能被提升。
4. 声明变量:使用var声明的变量会自动被添加到最近的环境中。没有使用var声明,该变量会自动被添加到全局变量中。(《JavaScript高级程序设计》)
注意:这里的没有使用var声明指的是从当前作用域向上延伸搜索,直到在全局作用域中都没有找到该变量的声明,此时该变量才会自动被添加到全局变量中。(参考上面理解要点“2”)
好啦,以下抛出题目,可以先试着做一下,你的答案是什么 ^_^
一.
var foo = 1;
function bar( ) {
foo=10;
return function foo() { };
}
bar( );
console.log(foo);
二.
var foo = 1;
function bar() {
foo = 10;
return;
function foo() {};
}
bar();
console.log(foo);
三.
var a = 1;
function fn() {
console.log(a);
var a = 2;
}
fn();
console.log(a);
四.
var a = 1;
function fn(a) {
console.log(a);
var a = 2;
}
fn(a);
console.log(a);
华丽丽的分割线———————————————————————————————————————————
哈哈,是不是so easy,以下是自己的理解,如果有误,还望大神指出^_^
一.
var foo = 1;
function bar( ) {
foo=10;
return function foo() { };
}
bar( );
console.log(foo);
理解要点:
1. 在bar()函数作用域中,foo 变量并没有使用 var 进行声明 ,所以在执行 foo = 1; 语句时,引擎会沿着作用域链向上查找,结果在全局作用域中找到了 var foo;此时全局作用域中的 foo 的值为 1;执行了 bar() 函数中的 foo = 10;后,最终全局作用域中的变量 foo 的值为 10;
2. return function foo(){}; 在此处是一个函数表达式,而不是函数声明,所以不存在函数声明的提升。
所以:
var foo = 1;
function bar( ) {
foo=10;
return function foo() { };
}
bar( );
console.log(foo);//
以下抛出题一的变形和答案,可以自行理解喔 ^_^
function bar( ) {
foo=10;
return function foo() { };
}
bar( );
console.log(bar());//ƒ foo() { }
console.log(foo);//
function bar( ) {
var foo=10;
return function foo() { };
}
bar( );
console.log(foo);//foo is not defined
二.
var foo = 1;
function bar() {
foo = 10;
return;
function foo() {};
}
bar();
console.log(foo);
理解要点:
1. bar()函数作用域中,function foo(){};语句虽然在 return;语句后面,对的,return;语句后的所有语句都不会被执行,但是在执行代码前,函数声明会被提前处理,此时函数声明语句会被提升到当前作用域的最前面。即实际上是这样的:
var foo = 1;
function bar() {
function foo() {};
console.log(foo);//ƒ foo() {}
foo = 10;
console.log(foo);//10
return;
function foo() {};//return;后的语句不执行
console.log(foo);
}
bar();
console.log(foo);
2. 既然 bar()函数作用域中已经有了 foo 的声明,说明 bar()中 foo 只是一个局部变量,在 bar()执行完毕就会被销毁,不影响全局作用域中的 foo 变量,所以:
var foo = 1;
function bar() {
foo = 10;
return;
function foo() {};
}
bar();
console.log(foo);//
三.
var a = 1;
function fn() {
console.log(a);
var a = 2;
}
fn();
console.log(a);
理解要点:
1. 函数 fn()的变量声明语句var a = 2;会提升;
2. fn ()存在函数局部变量 a;与全局作用域中的变量 a 互不影响;
所以实际上是这样的:
var a = 1;
function fn() {
var a;
console.log(a);//undefined
a = 2;
console.log(a);//
}
fn();
console.log(a);//
即:
var a = 1;
function fn() {
console.log(a);//undefined
var a = 2;
}
fn();
console.log(a);//
四.
var a = 1;
function fn(a) {
console.log(a);
var a = 2;
}
fn(a);
console.log(a);
理解要点:
1. 函数形参是存在于函数作用域中的局部变量,所以此题 fn(a)中相当于声明了一个局部变量 a;
2. fn(a);相当与 fn(1);
所以:
var a = 1;
function fn(a) {
console.log(a);
var a = 2;
}
fn(a);
console.log(a)//
又是华丽丽的分割线———————————————————————————————————————————
以下另外一些思考题,可以自行理解喔 ^_^
var foo = 0;
(function fn1(){
foo = 1;
console.log(foo);//
(function fn2(){
var foo = 2;
console.log(foo);//
(function fn3(){
foo = 3;
console.log(foo);//
}());
}());
}());
console.log(foo);//
(function fn1(){
(function fn2(){
(function fn3(){
foo = 3;
}());
}());
}());
console.log(foo);//
(function fn1(){
(function fn2(){
var foo;
(function fn3(){
foo = 3;
}());
}());
}());
console.log(foo);//Uncaught ReferenceError: foo is not defined
JS 函数作用域及变量提升那些事!的更多相关文章
- JS _函数作用域及变量提升
虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...
- JS中作用域和变量提升(hoisting)的深入理解
作用域(Scoping) javascript作用域之所以迷惑,是因为它程序语法本身长的像C家族的语言.我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间.在这样的一些空间里,外部 ...
- 原型模式故事链(4)--JS执行上下文、变量提升、函数声明
上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...
- JS作用域、变量提升和闭包
作用域 作用域可以理解为JS引擎执行代码的时候,查找变量的规则. 从确定变量访问范围的阶段的角度,可以分为2类,词法作用域和动态作用域.js是词法作用域. 从变量查找的范围的角度,可以分为3类,全局作 ...
- javascript中的变量作用域以及变量提升
在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...
- javascript中的变量作用域以及变量提升详细介绍
在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...
- JS函数——作用域
一 : 作用域的相关概念 首先看下 变量作用域 的概念:一个变量的作用域是程序源代码中定义这个变量的区域.————————<javascript权威指南>第六版全局变量拥有全局作用域,函数 ...
- Javascript作用域和变量提升
下面的程序是什么结果? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 结果是10: 那么 ...
- JS函数作用域及作用域链理解
从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...
随机推荐
- MPLS VPN随堂笔记3
跨域 ASBR之间运行MPBGP 1.配置AS内部IGP保证环回口互相可达,同时建立LDP邻居 (优先启用 mpls label rang 16 100)方便查看实验现象 2.配置PE1-PE2 PE ...
- 2015级软工实践k班第一次作业-准备
第一次作业-准备······ 几篇文章阅读下来发现一个事实,还是要有明确的目标,清楚自己需要做什么最为重要.然后根据目标确定需要为之所做的准备工作,考研也好,工作也罢,都是服务于自己的目标. 问题答应 ...
- sudoku--SE第二次作业
git传送门 编译环境: windows10.vs2017 所用语言: c++ 首先作为一个晚上闭眼的玩家,我先来讲一下我的心路历程: 最开始接到作业的时候心里是拒绝的,刚出了一趟小远门就这样,就很难 ...
- 聊聊React高阶组件(Higher-Order Components)
使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...
- java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector
在使用C3P0连接池的时候,发现了这个错误-.原来要使用C3P0的使用,不仅仅要导入c3p0-0.9.2-pre1.jar这个jar包,还要导入mchange-commons-0.2.jar这个jar ...
- CVE-2016-10191 FFmpeg RTMP Heap Buffer Overflow 漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 一.前言 FFmpeg是一个著名的处理音视频的开源项目,使用者众多.2016年末paulcher发现FFmpeg三个堆溢出漏洞分别为CVE-2016-10190 ...
- Qt Creator编译运行成功,但是显示系统找不到指定的文件(比如urlmon.dll动态链接库)
问题: 以前自己写的一个QT界面程序,在win 7 的32位系统上运行没有出现任何问题,但是重装系统之后,同样的程序放到win10 的64位系统下运行会出现警告:onecoreuap\inetcore ...
- Java中数组的概念
1.什么是二维数组?有几种表达方式?分别是什么? 答:多维数组即数组的数组,即数组的元素也是数组. 例:int[] [] a = {{1},{1,2},{1,2,3}}; 有三种方式 1).int [ ...
- Bootstrap——一款超好用的前端框架
前 言 Bootstrap Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,用于开发响应式布局.移动设备优先的 WEB 项目.Bootstrap在JQuery的基础上进 ...
- 参加Java培训你必须知道的五点真相!
相信大家都有过到招聘网站投简历.找工作的经历.当一份份简历发出三天后,左等右等连一个电话没有等来,心中不免有些失落,有些焦虑.这个时侯,很多培训机构就会纷纷给你打电话以各种名义让你参加各种IT技能培训 ...