在ES6之前,javascript只有全局作用域和函数作用域。所谓作用域就是一个变量定义并能够被访问到的范围。也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这个变量定义在函数内部,那么就只能在函数内部访问到这个变量。

全局作用域只要页面没关闭就会一直存在,而函数作用域只有在函数执行的时候才存在,执行完就销毁。且每次执行函数都会创建一个新的作用域。

那么什么是作用域链呢?

在了解作用域链之前,我们先了解一个执行期上下文的概念。

执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象(即AO或GO),一个执行期上下文定义了一个函数的执行环境,函数每次执行时对应的执行期上下文都是独一无二的,所以每次调用一个函数都会创建一个新的执行期上下文,当函数执行完毕,所产生的执行期上下文被销毁。

作用域链就是函数中[[scope]]属性所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

作用域链更像是一种包含的关系。比如说函数A内部定义了一个函数B,所以B的定义是依赖于A的,也就是说B在A的内部,那么B中就可以访问A的中的变量和方法。这种一层一层向上依赖的关系就构成了作用域链。

为了更好理解,我们直接看例子。

var name = 'xiaoyu';
function fn1() {};
function fn2() {
var num = 10;
function fn3() {
var num1 = 10;
console.log(num);
};
return fn3;
}
var fn4 = fn2();

在上个例子我们知道,fn2执行的时候返回fn3,产生了闭包。但是一个函数执行然后返回另一个函数都会产生闭包嘛?我们来看一下。

var name = 'xiaoyu';
function fn1() {};
function fn2() {
var num = 10;
function fn3() {//fn3函数没有依赖fn2函数内的变量
var num1 = 10;
console.log(num1);
};
return fn3;
}
var fn4 = fn2();

了解了作用域链之后,我们来看一个小例子,巩固一下。

var age = 10;
var obj = {
age: 12,
test: function() {
console.log(age);
console.log(obj.age);
console.log(this.age);
}
}
obj.test();

console.log(this.age)打印出12不难理解,但是为什么console.log(age)不也应该打印出12嘛。

我们说test执行时首先会在自己的作用域内查看有没有age变量,然后再沿着作用域链往上到全局作用域查找age变量,全局作用域下有age变量和data变量。所以console.log(age)打印出的10,如果要打印出12则需要访问obj.age。

ES6的块级作用域

在ES6之后,通过let和const引入了块级作用域。即通过let和const声明的变量只在声明所在的块级作用域内有效,并且let声明的变量虽然属于全局变量,但不再属于全局对象window。

我们通过一段代码来看一下引入块级作用域后,函数的作用域链的变化。

var age = 10;
let obj = {
age: 12,
test: function() {
console.log(age);
console.log(obj.age);
console.log(this.age);
}
}
obj.test();

从函数作用域和块级作用域看javascript的作用域链的更多相关文章

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

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

  2. Flask07 Jinja2模板测试器、控制语句IF/FOR、变量/块 赋值、作用域、块级作用域

    1 测试器及其使用 在模板中的 {{}} 可以书写测试器,格式如下 {{ 变量 is 测试器名称  }} 1.1 在python中导入 Jinja2 的模板 from jinja2 import te ...

  3. JavaScript的作用域和块级作用域概念理解

    作用域 作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期.说到这里我们需要理解两个概念:块级作用域与函数作用域. 函数作用域 这个应该好理解,函数作用域就是说定义在 ...

  4. JavaScript 学习-变量的作用域和块级作用域

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 函数作用域和块级作用域--你不知道的JavaScript

    et和const在{}内声明都会变为外部不能访问的值,但是const声明的是常量,也不能修改 函数是 JavaScript 中最常见的作用域单元.本质上,声明在一个函数内部的变量或函数会在所处的作用域 ...

  6. 匿名函数块级作用域以及在JQuery中的应用

    最近经常回在群里面看到有些朋友问如下这样的js写法该如何理解的的问题,虽然可能对匿名函数有些理解,但是有时候看到JQuery源码或者其他JS库中同样的写法时,就有点不理解了,今天再次分享下这方面的知识 ...

  7. JavaScript 作用域 匿名函数 模仿块级作用域(私有作用域)

    作用域 对于有块级作用域的语言来说,for语句中定义并初始化的变量i在循环外是无法访问的. 而javascript没有块级作用域,for语句中定义的变量i在循环结束后,依旧会存在于循环外部的执行环境( ...

  8. Javascript高级编程学习笔记(25)—— 函数表达式(3)模仿块级作用域

    昨天写了闭包 今天就来聊聊块级作用域的事情 在绝大多数编程语言中,都有块级作用域这个概念 什么是块级作用域呢? 前面我们在刚开始讲的时候说过,JS中的大括号(不在赋值运算符的后面)表示代码块 块级作用 ...

  9. JavaScript模仿块级作用域

    avaScript 没有块级作用域的概念.这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,来看下面的例子: function outputNumbers(count){ for ( ...

随机推荐

  1. HTML中&nbsp; &ensp; &emsp; &thinsp;等6种空白空格

  2. 类1(this指针/const成员函数/类作用域/外部成员函数/返回this对象的函数)

    假设我们要设计一个包含以下操作的 Sales_data 类: 1.一个 isbn 成员函数,用于返回对象的 book_no 成员变量 2.一个 combine 成员函数,用于将一个 Sales_dat ...

  3. leecode刷题(1)-- 删除排序数组中的重复项

    删除排序数组中的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度.不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的 ...

  4. [Swift实际操作]九、完整实例-(4)在项目中使用CocoaPod管理类库和插件

    本文将为你演示,如何使用CocoaPod第三方类库管理工具,在项目中安装未来需要使用的类库.首先创建一份文本文件.可以使用一个脚本创建文件,你可以采用自己的方式是创建一份文本文件,接着在文件名称上点击 ...

  5. vmware vSphere虚拟网络之标准交换机(二)

    一.标准交换机的特点: 1)只能用于物理主机 2)其他主机不能共享同一个虚拟交换机 3)不具备任何灵活性 4)每台ESXi主机都要配置一遍 二.网络图: 三.创建标准交换机: 登录web vCente ...

  6. Python之路迭代器协议、for循环机制、三元运算、列表解析式、生成器

    Python之路迭代器协议.for循环机制.三元运算.列表解析式.生成器 一.迭代器协议 a迭代的含义 迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的 ...

  7. EL表达式的语法与应用

    EL(是Expression Language的缩写),使用EL对JSP输出进行优化,可以使得页面结构更加清晰,代码可读性高,也更加便于维护. EL表达式的语法: 语法:$(EL 表达式) $  和 ...

  8. C语言数据结构-链式队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作

    1.数据结构-链式队列的实现-C语言 typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef st ...

  9. 使用 v-model 实现 双向绑定.(子组件和父组件.)

    vue 自定义组件 v-model双向绑定. 父子组件同步通信   父子组件通信,都是单项的,很多时候需要双向通信.方法如下: 1.父组件使用:msg.sync="aa"  子组件 ...

  10. 洛谷 P3244 / loj 2115 [HNOI2015] 落忆枫音 题解【拓扑排序】【组合】【逆元】

    组合计数的一道好题.什么非主流题目 题目背景 (背景冗长请到题目页面查看) 题目描述 不妨假设枫叶上有 \(n​\) 个穴位,穴位的编号为 \(1\sim n​\).有若干条有向的脉络连接着这些穴位. ...