JavaScript作用域

JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.

—— JS权威指南

在JS里,一切皆对象,函数也是。

一、有什么用

什么时候会用到它?它的存在有什么意义?这是我在学习一个新知识的时候首先发起的疑问。那么,在JavaScript里,作用域有什么用?

作用域规定了变量和函数的可访问范围,这个可访问范围可以细分为两个场景:变量和函数的可见性和生命周期。

  • 可见性:当访问某个变量的时候,访问的是局部变量还是全局变量?重复命名了多个变量,到底访问的是哪个值?这个变量现在能不能用,为什么有时候会返回undefined?
  • 生命周期:变量是一直存在在内存中么?什么时候会被销毁?比如定义在函数内部的变量被称为局部变量,这个变量只存在函数内部,函数调用后将会被销毁,等等...当然如果有闭包什么的就要另当别论,在这里只讨论最一般的情况。

二、全局作用域 & 局部作用域

//函数一
var authorName = "jennifer"; function doSomething() { anotherName = "james"; var blogName = "smoothlily";
function innerSay() {
alert(blogName);
}
innerSay();
} console.log(authorName); //jennifer
doSomething(); //smoothlily
console.log(anotherName); //james
console.log(blogName); //脚本错误
innerSay(); //脚本错误

针对可见性这个问题,可以聊一聊JS中规定的两个作用域:全局作用域,局部作用域。

  • 全局作用域(Global Scope)

    在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:

最外层函数和在最外层函数外面定义的变量拥有全局作用域:

如函数一的变量authorName。

所有未定义直接赋值的变量自动声明为拥有全局作用域:

如函数一的anotherName。

这种情况在写代码时最好不要出现,想要拥有全局作用域的变量还是乖乖的在脚本最开始显性声明全局变量。

所有window对象的属性拥有全局作用域,例如window.name、window.location、window.top等等

  • 局部作用域(Local Scope)

和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的就是函数内部:如函数一的blogName。

三、作用域链(Scope Chain)

在说作用域链的时候,要分为两个“时间点”:函数创建时以及函数执行时

这里借用梦想天空做的两个图:

函数创建时:

function add(num1,num2) {
var sum = num1 + num2;
return sum;
}

函数在创建时,会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性,使其包含创建函数的那个时刻下,作用域中对象的集合,也就是函数的作用域链,这个作用域链直接决定哪些数据被函数访问。

函数执行时:

var total = add(5, 10)

函数执行时,创建一个活动对象,活动对象在一开始的时候,只包含arguments对象。

当遇到变量声明时:

var a = 10;

会将这个变量复制到活动对象中。

当遇到变量访问时,会沿着作用域链做标识符解析(后续会提到),直至找到这个变量。

活动对象包含了函数的所有局部变量、命名参数、参数集合以及this,这些值按照它们出现在函数中的顺序被复制到活动对象中。然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。

标识符解析

作用域链的用途,是为了保证对执行环境有权访问的对象的有序访问。标识符解析沿着作用域链一级一级地搜索标识符。搜索过程始终从作用域链的最前端开始(活动对象),逐级向后访问(直到全局对象),直至找到标识符为止,如果找不到,则会报错。

其他书单

JavaScript框架设计-司徒正妹

大放异彩的伪元素——可以做什么?

当我们谈论颜色时,我们在谈论什么 - 基础知识篇

参考文献

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

Javascript作用域原理

[JavaScript] JavaScript作用域深度解析的更多相关文章

  1. Javascript的作用域和闭包(一)

    一.作用域是什么? 几乎所有的编程语言最基本的功能之一,就是能够存储变量的值,并且能访问和修改这些值. 修改变量值的过程我们通常在程序执行时,称为改变一个对象的状态.有了状态,让程序变得有非常有趣. ...

  2. [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析

    [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...

  3. 深度解析javascript中的浅复制和深复制

    原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...

  4. 42套JavaScript深度解析教学视频!合集

    本文首发于:风云社区SCOEE(社区旨在普惠软件.图片.音乐.视频.素材.文档等互联网资源.为大众提供多样化的服务,以及主要涵盖学术科学.电脑技术.文化人文.体育健身等领域的知识和信息,获得用户的支持 ...

  5. 深度解析javaScript常见数据类型检查校验

    前言 在JavaScript中,数据类型分为两大类,一种是基础数据类型,另一种则是复杂数据类型,又叫引用数据类型 基础数据类型:数字Number 字符串String 布尔Boolean Null Un ...

  6. JavaScript从作用域到闭包

    目录 作用域 全局作用域和局部作用域 块作用域与函数作用域 作用域中的声明提前 作用域链 函数声明与赋值 声明式函数.赋值式函数与匿名函数 代码块 自执行函数 闭包  作用域(scope) 全局作用域 ...

  7. JavaScript中---作用域

    作用域: 变量还有函数作用的范围. 浏览器的内核主要有两大功能,一个是渲染页面,另一个就是我们的JavaScript的解释器了. 我们主要来说说JavaScript解释器,在解析时是怎么样的工作原理. ...

  8. 浅谈JavaScript的作用域

    前段时间学了下JavaScript作用域,这个东西在JavaScript非常重要,也是JavaScript很基础的东西,正如少林里面基础武功,有了基础,才能学绝世武功. 作用域的作用是啥?一套设计良好 ...

  9. JavaScript的作用域与作用域链

    作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.可以说,变量和函数在什么时候可以用,什么时候被摧毁,这都与作用域有关. JavaScript中,变量的作用域有全局 ...

随机推荐

  1. Java学习日记-10 集合

    集合(Collection) 1. 什么是集合? 集合是一组对象组成的一个整体,又称为容器,集合类属于java.util包.集合不同于数组的地方在于,一是它的容量是可变的,二是集合中只能存储对象,不能 ...

  2. Spring JDBC 随笔

    Spring 框架,借助 JdbcTemplate 类来简化 java 访问 database. 完成一个增查改删(CRUD)的基本功能,借助下面 5 个角色来共同来完成. 1. object cla ...

  3. linux关闭防火墙及selinux

    RHEL6.5 查看linux防护墙状态: service iptables status 关闭linux防火墙: 1)永久关闭,重启后生效 开启: chkconfig iptables on 关闭: ...

  4. 使用javascript判断浏览器类型

    之前在项目中遇到过要针对不同浏览器做不同的一些js或者css操作,后来某个朋友也突然问到这个问题,所以,整理了一下,在这里留个笔记,方便以后使用. 使用javascript判断浏览器类型: funct ...

  5. struts2校验器规范错误解决

    今天struts2的校验器的配置文件文件头出现了错误,配置如下: <!DOCTYPE validators PUBLIC        "-//OpenSymphony Group// ...

  6. Android学习_ContentProvider和Uri

    ContentProvider概述 public abstract class ContentProvider extends Object implements ComponentCallbacks ...

  7. [Android Webkit]JNI基础及Java层与C++层的交互

    1. JNI 注册 1.1. JNI的基础结构       JAVA == JNI == Native Code      JNI(Java Native Interface)是Java与Native ...

  8. Java 编程的动态性,第 5 部分: 动态转换类--转载

    在第 4 部分“ 用 Javassist 进行类转换”中,您学习了如何使用 Javassist 框架来转换编译器生成的 Java 类文件,同时写回修改过的类文件.这种类文件转换步骤对于做出持久变更是很 ...

  9. 常用PC服务器LSI阵列卡配置

    通常,我们使用的DELL/HP/IBM三家的机架式PC级服务器阵列卡是从LSI的卡OEM出来的,DELL和IBM两家的阵列卡原生程度较高,没有做太多封装,可以用原厂提供的阵列卡管理工具进行监控:而HP ...

  10. ServletContextListener 解析用法

    ServletContext 被 Servlet 程序用来与 Web 容器通信.例如写日志,转发请求.每一个 Web 应用程序含有一个Context,被Web应用内的各个程序共享.因为Context可 ...