虽然看了多次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 _函数作用域及变量提升的更多相关文章

  1. JS 函数作用域及变量提升那些事!

    虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...

  2. JS中作用域和变量提升(hoisting)的深入理解

    作用域(Scoping) javascript作用域之所以迷惑,是因为它程序语法本身长的像C家族的语言.我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间.在这样的一些空间里,外部 ...

  3. JS基础_函数作用域

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  5. javascript中的变量作用域以及变量提升详细介绍

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...

  6. Javascript作用域和变量提升

    下面的程序是什么结果? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 结果是10: 那么 ...

  7. js的函数作用域跟块级作用域

    js的函数作用域跟块级作用域(原文地址:http://blog.csdn.net/huangjq36sysu/article/details/51085674)

  8. js 作用域,变量提升

    先看下面一段代码: 代码执行的结果是: 1st alert : a = 0 2nd alert : a = undefined 5th alert : a = 0 3rd alert : a = 3 ...

  9. js中变量的作用域、变量提升、链式作用域结构

    一:作用域 在ES6之前,javascript没有块级作用域(一对{}即为一个块级作用域),只有全局作用域和函数作用域(局部),因此,对应的有全局变量和局部变量.在函数内部可以访问到全局变量,但在函数 ...

随机推荐

  1. 深入学习CSS外边距margin(重叠效果,margin传递效果,margin:auto实现块级元素水平垂直居中效果)

    前言 margin是盒模型几个属性中一个非常特殊的属性.简单举几个例子:只有margin不显示当前元素背景,只有margin可以设置为负值,margin和宽高支持auto,以及margin具有非常奇怪 ...

  2. JS转换HTML转义符,编码及解码

    JS转换HTML转义符 //去掉html标签 function removeHtmlTab(tab) { return tab.replace(/<[^<>]+?>/g,'') ...

  3. [物理学与PDEs]第2章第1节 理想流体力学方程组 1.2 理想流体力学方程组

    1.  质量守恒定律: 连续性方程 $$\bee\label{2_1_2_zl} \cfrac{\p\rho}{\p t}+\Div(\rho{\bf u})=0.  \eee$$ 2.  动量守恒定 ...

  4. [物理学与PDEs]第1章第9节 Darwin 模型 9.1 拟静电模型及其修正形式

    1. 拟静电模型: 当 $\cfrac{\omega}{c}\ll \cfrac{1}{c}\lra \omega\ll \cfrac{c}{l}$ 时, $$\bex \cfrac{1}{c}\cf ...

  5. 计算 $\dps{\int_0^\infty\frac{\sin^2x}{x^2}dx=\frac{\pi}{2}}$

    计算 $\dps{\int_0^\infty\frac{\sin^2x}{x^2}dx=\frac{\pi}{2}}$. 由分部积分, $$\bee\label{1}\bea \int_0^\inft ...

  6. LINQ to SQL 的常见异常及解决办法

    Ø  简介 本文主要介绍 LINQ to SQL 中常见的异常,以及对应的解决办法.包括以下内容: 1.   左连接情况下,右表非空类型字段可能抛出异常 1.   左连接情况下,右表非空类型字段可能抛 ...

  7. selenium新手常遇到的坑

    本文是以Chrome为例: 1.Chrome相对应的chromedriver的版本信息[点击浏览器的右上角的浏览器信息--------帮助-------关于Google Chrome查看相对应的信息- ...

  8. hibernate之Configuration对象

    任务:读取主配置信息 1.  Configuration config = new Configuration();      使用hibernate,但并没有读取 2.  config.config ...

  9. Mysql中设置指定IP的特定用户及特定权限

    创建用户:格式:grant select on 数据库.* to 用户名@登录主机 identified by '密码' 举例: 例 1:增加一个用户 test1 密码为 abc,让他可以在任何主机上 ...

  10. SecureCRT的安装与破解(过程很详细!!!)

    SecureCRT的安装与破解(过程很详细!!!) 使用SecureCRT可以方便用户在windows环境下对linux主机进行管理,这里为大家讲一下SecureCRT的破解方法,仅供大家参考学习: ...