作用域和作用域链方面的知识是JS的重点,去面试十个有八个都会问你这块的知识,所以说这块是特别特别的重要,下面我们好好理解一下作用域和作用域链到底是个什么:

先上一段代码:

var a = 'jack';
function fn() {var a = 'frank';
}
console.log(a);

我们在函数里定义了一个a变量,在函数外也定义了一个a变量,那最后输出的应该是哪一个a的值呢?

这个时候就有了作用域这个概念了,简单地说作用域就是限制某个变量只能在某个区域内有效

作用域有全局作用域和局部作用域之分,变量同样如此,在上例中,第一个a很显然是一个全局变量,函数内的a显然是局部变量。全局变量拥有全局作用域而局部变量拥有局部作用域。这道题里console.log是在全局里调用a,那么毋庸置疑最后输出的一定是'jack'。

这个时候我把函数代码块改为if代码块,看看最后应该输出什么呢

var a = 'jack';
if(true) {var a = 'frank';
}
console.log(a);

最后的结果a输出的是'frank'。

实际上这里有一个大坑,千万不要以为大括号封起来就一定是封闭环境,if里面的语句执行完后就会自动销毁了,但是在javascript里if内部定义的变量就会变为当前执行环境的变量。当前执行环境在最外围,所以if里面的a就变为全局变量了

我们再来看下面这段代码分别应该输出什么呢?

for(var i = 0;i<3;i++) {break;
}
console.log(i);
k = 5;
while(k>1) {k--;var d = 10;
}
console.log(k);
console.log(d);

除了if代码块还有我们常见的for循环,while循环也是相似的结果,我们不要被括号给迷惑了,在括号内定义的变量不一定就是局部作用域,因此这里的i,k,d变量都是全局变量,这是输出结果:

下面结合es6新增的块级作用域做一个总的概括:

  • 在ES6中只要{ }没有和函数结合在一起,那么应该就是“块级作用域”。
  • 在块级作用域中,var定义的变量是全局变量,let定义的变量是局部变量。
  • 而在局部作用域也就是函数作用域中,无论是用var定义的变量还是用let定义的变量都是局部变量。
  • 无论是在块级作用域还是局部作用域,省略变量前面的var或者let都会变成一个全局变量。

现在我们再回到前面的例子,这一次增加了全局变量b,在函数内增加了两个console.log输出语句,最后再调用这个函数,但是在函数里并没有定义变量b,那最后会是什么结果呢

var a = 'jack';
var b = 'andy';
function fn() {var a = 'frank';console.log(a);console.log(b);
}
fn();
console.log(a);

输出结果:

第二个console.log为什么会输出全局变量andy呢?

这个时候就有了作用域链的概念了,简单的说作用域表示区域,作用域链表示次序

现在我们把眼光放在函数fn里,第一行定义了a是局部变量,第二行输出这个a,但是整个代码里定义了两个a,那么就需要刚刚说到的作用域链来决定到底先用哪个变量。

javascript会先看函数内有没有这个变量a,如果没有再去函数的外围看有没有这个变量,这里作用域链就帮我们安排好了这个次序。

所以,函数内定义了变量a为'frank',那么第二行就会输出'frank',第三行要输出变量b,我们先看函数内有没有这个变量,发现没有,再去外围发现有全局变量b,那么输出的就是这个值,我们再来看最后一个console.log(a),因为他在全局范围内,所以只能访问全局变量a。

也就是说:作用域链只能向上查找,最终找到全局。不能同级(局部)或者向下查找

我们再看这一段代码:

var a = 'jack';
function fn() {console.log(a);var a = 'andy';console.log(a);
}
fn();

我们思考一下会输出什么呢?

输出结果:

稍微有点js经验的同学应该都会答对,因为有变量提升,变量a在第一行就被声明了,只不过没有被赋值。下面修改一下代码,大家再看看会输出什么:

var a = 'jack';
function fn() {console.log(a);var a = 'andy';console.log(ss());function ss() {return a;}
}
fn();

我们在fn函数内又添加了一个函数ss,并且在这个函数的顶部就调用了这个函数。不仅函数内声明的变量会被提升,函数内的函数也会被提升,而且函数的提升会比变量更优先

那么,在javascript中这段代码实际上是这样被执行的:

var a = 'jack';
function fn() {function ss() {return a;}var a;console.log(a);a = 'andy';console.log(ss());
}
fn();

先把函数声明提升到首行,再声明变量a,然后输出a,a没有被赋值,所以是undefined,然后a被赋值为'andy',最后调用函数ss,返回的就是andy。

详解JS 作用域与作用域链相关推荐

  1. 详解JS原型与原型链

    目录 1.构造函数原型prototype 2.对象原型__proto__ 3.constructor构造函数 4.原型链 5.原型对象中的this指向 6.扩展内置对象(原型对象的应用) 在ES6之前 ...

  2. 详解JS原型链与继承

    详解JS原型链与继承 JavaScript 目录 摘自JavaScript高级程序设计: 概念 确定原型和实例的关系 原型链的问题 借用构造函数 组合继承 原型继承 寄生式继承 寄生组合式继承 new ...

  3. 详解js中的继承(一)

    详解js中的继承(一) 前言 准备知识 1.构造函数,实例 2.原型对象 3.构造函数,原型对象和实例的关系 继承 原型链 小结 前言 通过[某种方式]让一个对象可以访问到另一个对象中的属性和方法,我 ...

  4. 详解JS中的Object

    详解 JS 中的 Object 从本质上看,Object 是一个构造函数,用于创建对象. 一.Object 构造函数的属性 在 Object 中声明的属性只有两个: Object.length -- ...

  5. python获取mysql中的数据供js调用_详解js文件通过python访问数据库方法

    我来教你 js文件怎么通过python访问数据库,希望能够为你带来帮助. 1.如果是要提交表单内容给 服务器的 python 处理,那么只需要在表单 里面的 action 填写服务端的处理路由就可以了 ...

  6. socket服务器断开消息,详解JS WebSocket断开原因和心跳机制

    1.断开原因 WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来. ws.onclose = function (e) { console.log('websocket ...

  7. php js实现流程图,详解js中构造流程图的核心技术JsPlumb(2)_javascript技巧

    前言:上篇详解js中构造流程图的核心技术JsPlumb介绍了下JsPlumb在浏览器里面画流程图的效果展示,以及简单的JsPlumb代码示例.这篇还是接着来看看各个效果的代码说明. 一.设置连线的样式 ...

  8. 详解js对称加密和非对称加密

    详解js对称加密和非对称加密 https保证数据在传输过程中不被窃取和篡改,从而保证传输安全 1.加密 对称加密:产生一个密钥,可以用其加密,可以用其加密,也可以用其加解密. 这个密钥可以是任何东西, ...

  9. 详解 js 函数中的 arguments

    详解 js 函数中的 arguments 1.什么 arguments 简单来说:arguments 是一个对应于传递给函数的参数的类数组对象 arguments 对象是所有(非箭头)函数中都可用的局 ...

  10. linux 弹出窗口,实现弹出窗口的window.open用法详解(js代码)

    实现弹出窗口的window.open用法详解(js代码) [1.最基本的弹出窗口代码] 其实代码非常简单: 因为这是一段javascripts代码,所以它们应该放在 cript">标签 ...

最新文章

  1. Python使用tpot获取最优模型并抽取最优模型模型参数
  2. 【响应式Web前端设计】new Option()函数的作用(三区联动)
  3. Eigen 学习笔记
  4. C# WebApi+Task+WebSocket实战项目演练(四)
  5. Streamy 使用RDBMS
  6. .net中的mapinfo开发:准备(一)
  7. NOT IN、JOIN、IS NULL、NOT EXISTS效率对比
  8. AliOS Things v1.1.2新特性
  9. android 桌面视频播放器,ZY-Player ,一款跨平台桌面端视频资源播放器
  10. 设计模式--代理模式--Java实现
  11. 程序包sun.misc不存在
  12. Cocos2dx 下面,对 音乐 和音效简单封装
  13. AI 时代,程序员从小白到小牛的发展攻略丨今晚直播送机械键盘!
  14. 三大抽样分布——卡方分布、t分布、F分布
  15. 卷积神经网络(CNN)实现手写体识别
  16. python聊天室_python聊天室
  17. 计算机系云,计算机与信息技术学院
  18. Learning Convolutional Neural Network for Graphs
  19. GPIB编程控件指令
  20. 研究生入门,如何高效阅读论文

热门文章

  1. pycharm 设置字体大写和高亮字体颜色
  2. 老毛子固件padavan挂载USB摄像头躺过的坑
  3. TCP/IP协议知识科普
  4. 设计传感器,需要注意哪些问题
  5. 全微分/偏导数/方向导数/梯度/全导数
  6. FIDO标准 无密码身份认证登录
  7. 新年伊始:再谈数据安全治理
  8. 志宇-mysql优化
  9. 三菱plc pwm指令_电厂技术 | 学习三菱PLC编程入门应先学习什么?想学习三菱PLC的朋友一定要看的入门第一课...
  10. SpringIoC和SpringMVC的快速入门