JS函数作用域及作用域链理解
从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解。欢迎大牛拍砖吐糟。
变量作用域
在JavaScript中全局变量的作用域比较简单,它的作用域是全局的,在代码的任何地方都是有定义的。然而函数的参数和局部变量只在函数体内有定义。另外局部变量的优先级要高于同名的全局变量,也就是说当局部变量与全局变量重名时,局部变量会覆盖全局变量(如下面例子)。
var num = 1; //声明一个全局变量
function func() {
var num = 2; //声明一个局部变量
return num;
}
console.log(func()); //输出:2
注:声明局部变量时一定要使用var,否则,解释器会将该变量当做全局对象window的属性。
函数作用域
在JavaScript中变量的作用域,并非和C、Java等编程语言似得,在变量声明的代码段之外是不可见的,我们通常称为块级作用域,然而在JavaScript中使用的是函数作用域(变量在声明它们的函数体以及这个函数体嵌套的任意函数体都是有定义的)。(如下面的例子)
function func() {
console.log(num); //输出:undefined,而非报错,因为变量num在整个函数体内都是有定义的
var num = 1; //声明num 在整个函数体func内都有定义
console.log(num); //输出:1
}
func();
注:JavaScript的函数作用域是指在在函数内声明的所有变量在函数体内始终是可见的,也就是说在函数体内变量声明之前就已经可用了。
作为属性的变量
当声明一个全局变量的时候,实际上是定义了全局对象window的一个属性。
var num = 1; //声明全变量num
alert(window.num) //输出:1 声明的全局变量实际上就是声明了一个window对象的属性
作用域链
在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
当一个函数创建后,它实际上保存一个作用域链,并且作用域链会被创建此函数的作用域中可访问的数据对象填充。例如定义下面这样一个函数:
function func() {
var num = 1;
alert(num);
}
func();
在函数func创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图所示(注意:图片只例举了全部变量中的一部分):
函数add的作用域将会在执行时用到。例如执行如下代码:
执行此函数时会创建一个称为“运行期上下文(execution context)”(有人称为运行环境)的内部对象,运行期上下文定义了函数执行时的环境。每个运行期上下文都有自己的作用域链,用于标识符解析,当运行期上下文被创建时,而它的作用域链初始化为当前运行函数的[[Scope]]所包含的对象。
这些值按照它们出现在函数中的顺序被复制到运行期上下文的作用域链中。它们共同组成了一个新的对象,叫“活动对象(activation object)”,该对象包含了函数的所有局部变量、命名参数、参数集合以及this,然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。新的作用域链如下图所示:
JS函数作用域及作用域链理解的更多相关文章
- [js]函数的上级作用域,他的上级作用域就是谁,跟函数在哪执行的没什么关系.
函数的上级作用域,他的上级作用域就是谁,跟函数在哪执行的没什么关系. <script> //如何查找上级作用域? //看函数在哪个作用域下定义的,他的上级作用域就是谁. 跟函数在哪执行的没 ...
- JS函数、变量作用域
函数参数 函数的()中指定一个或多个形参(形式参数),多个形参之间用,号隔开,声明形参相当于在函数内部声明了对应的变量,但不赋值.在调用时在()中指定实参 调用时解析器不会检查实参类型.数量,实参可 ...
- js函数自动执行的一点理解
//声明一个匿名函数并赋值给一个变量 var a = function(){ console.log("executing..."); } //匿名函数调用 a(); 相信上面这段 ...
- js函数节流和防抖的理解与实现
一:函数防抖1.理解:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间2.思路:每次触发事件时都取消之前的延时调用方法 3.实现: function debounce ...
- js对象系列【二】深入理解js函数,详解作用域与作用域链。
这次说一下对象具体的一个实例:函数,以及其对应的作用域与作用域链.简单的东西大家查下API就行了,这里我更多的是分享自己的理解与技巧.对于作用域和作用域链,相信绝大多数朋友看了我的分享都能基本理解,少 ...
- 通过作用域链解析js函数一些难以理解的的作用域问题
基本原理 js函数在执行时,系统会创建一个隐式的属性scope,scope中存储的是函数的作用域链. 通过对这个scope的分析,就能解释JavaScript中许多难以理解的问题: 例1: funct ...
- 理解js中的作用域,作用域链以及闭包
作用域变量作用域的类型:全局变量和局部变量全局作用域对于最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的 <script> var outerVar = " ...
- js基础梳理-如何理解作用域和作用域链?
本文重点是要梳理执行上下文的生命周期中的建立作用域链,在此之前,先回顾下关于作用域的一些知识. 1.什么是作用域(scope)? 在<JavaScritp高级程序设计>中并没有找到确切的关 ...
- JS中的函数声明和函数表达式的区别,即function(){}和var function(){},以及变量提升、作用域和作用域链
一.前言 Uncaught TypeError: ... is not a function function max(){}表示函数声明,可以放在代码的任何位置,也可以在任何地方成功调用: var ...
随机推荐
- mysql root@::1 意义
root@::1 ::1 是IPv6格式的 127.0.0.1
- ShareSDK QQ分享失败的坑
QQ分享的话,有标题和内容字符数限制,QQ好友的话限制的很小,标题30字符,内容40字符.分享之前限制一下.
- jQuery提交form表单
<form id="search_form" name="search_form" method="post"> <inp ...
- Java基础笔记-多线程
线程: 方式一:继承Thread类并且复写run方法. 格式: class MyThread extends Thread { public void run() { 线程中要运行的代码. } } 其 ...
- T-SQL视图
视图(view) 用于存储封装一个select语句,使用方法和表一样.也可通过界面对视图进行操作. create view ordersWithNum --创建一个视图ordersWithNum as ...
- UVa 821 Page Hopping
题意: 给出一个有向图,求所有路径(两点间的最短路径)的平均值. 分析: 用floyd求两点间的最短距离,然后求平均就好. 代码: #include <iostream>#include ...
- 解决UITableView数据没有充满屏幕时,显示多余的空白cell的问题
#pragma mark 去除多余的线 -(void) clearExtrLine{ UIView *view = [[UIView alloc] init]; view.backgroundColo ...
- 总结PHP中几种常用的网页跳转代码
网页跳转的意思就是指当你在浏览器中访问A页面时,会自动跳转到B页面,往往网页跳转用在404页面中会比较多点.至于怎么实现网页跳转,网上已经提供了很多的方法,有些方法是不可行的,经过测试,叶德华今天就在 ...
- c++ :OOP之静态类型与动态类型
所谓静态类型即类型指针或引用的字面类型:而动态类型即类型指针或引用的实际类型. 这一对概念一般发生在基类和派生类之间. 如: class Base { ..... } class Derived : ...
- getpwuid()函数
linux getpwuid 得到指定用户信息 和系统数据相关的passwd 结构 和系统数据相关的一个结构passwd定义如下 /* The passwd structure. */ struct ...