深入理解javascript之作用域

简单地说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在javascript中,变量的作用域分为全局和局部两种。

拥有全局作用域就是在代码任何地方都能够访问到,叫做全局变量,以下三种情况可以拥有

全局作用域

最外层函数和最外层函数外面定义的变量:

var name="brizer";
function doSomething(){
    var realname="lf";
    function innerSay(){
        alert(realname);
    }
    innerSay();
}
document.write(name); //brizer
document.write(realname); //脚本错误
doSomething(); //lf
innerSay() //脚本错误

未定义直接赋值的变量:

/*全局作用域2:*/
function doSomething(){
    var name="brizer";
    realname="lf";
    document.write(name);
}
doSomething(); //brizer
document.write(realname); //lf

所有window对象:

一般情况下,所有window对象的内置属性都拥有全局作用域,如window.location等。

局部作用域

局部作用域只在固定的代码片段内可访问到。

如下代码:

function doSomething(){
    var name="lf";
    function innerSay(){
        alert(name);
    }
    innerSay();
}
alert(name); //脚本错误
innerSay(); //脚本错误

函数作用域

这里把函数作用域单独提出来讲并不是因为它和局部还有全局是平级关系,而是由于其比较特殊。JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。这是javascript权威指南中的一句话,相当经典。

举个例子说,

//函数运行在它们被定义的作用域里,而不是它们被执行的作用域
  var name = 'lf';
     function echo() {
          document.write(name);
     }

     function env() {
          var name = 'brizer';
          echo();
     }

     env();

最后结果的lf而不是brizer。说明函数在定义时,它的作用域就已经决定了。

作用域链

下面我们说说作用域链,在javascript中,函数也是对象,实际上,javascript中的一切都是对象。函数内部有一个只给javascript引擎访问的内部属性是[[scope]],该属性包含了函数创建时的作用域中对象的集合,这个集合就叫做作用域链。

比如下面代码:

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

在函数创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图:

当函数被执行时,会创建一个活动对象,该对象包含了函数所有局部变量、命名参数以及this,然后该对象会被推入作用域链的前端,当函数执行完毕,该对象也随之销毁。如下图:

可以看到,全局变量会被活动对象推到作用域链的最后端,这也就是为什么全局变量访问速度慢的原因!

with

一般情况下,作用域链只会被with和catch语句影响。当使创建用with的时候,函数会创建一个新的活动对象,推到最前端,该对象就是with的对象。这就意味着所有的局部变量都处于第二个作用域链对象中去了,这也就是为什么要避免使用with的原因。

function initUI(){
    with(document){
        var bd=body,
            links=getElementsByTagName("a"),
            i=0,
            len=links.length;
        while(i < len){
            update(links[i++]);
        }
        getElementById("btnInit").onclick=function(){
            doSomething();
        };
    }
}
时间: 2024-10-19 20:01:05

深入理解javascript之作用域的相关文章

深入理解javascript的作用域--函数声明为什么会前置

标签: javascript函数对象 这篇博文解决了以下迷惑 函数声明为什么前置 函数声明前置和变量前置优先级问题 为什么js文件开头就可以使用Math,String等库,而不需要导入头文件 1.变量对象VO 变量对象(Variable Object, 缩写为VO)是一个抽象 概念中的"对象",它用于存储执行上下文中的: 1. 变量 2. 函数声明 3. 函数参数 js解释器就是通过变量对象(VO)来找到我们定义的变量和函数的. 举个例子: var a = 10; function t

深入理解JavaScript变量作用域

JS变量作用域特点: a.JS变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数中都有定义. 1.作用域链 var rain = 1 ; function rainman(){ var man = 2 ; function inner(){ var innerVar = 4; alert(rain); } inner(); // 调用inner函数 } rainman(); // 调用rainman函数 观察alert(rain);这句

理解JavaScript中作用域链的关系

javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则是prototype.proto和constructor的三角关系.本文先用一张图开宗明义,然后详细解释原型的三角关系 概念 上图中的复杂关系,实际上来源就两行代码 function Foo(){}; var f1 = new Foo; [构造函数] 用来初始化新创建的对象的函数是构造函数.在例子中,Foo()函数是构造函数 [实例对象] 通过构造函数的new操作

彻底理解JavaScript原型

原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有"[[prototype]]"属性,函数对象有"prototype"属性,原型对象有"constructor"属性. 为了弄清原型,以及原型相关的这些属性关系,就有了这篇文章. 相信通过这篇文章一定能够清楚的认识到原型,现在就开始原型之旅吧. 认识原型 开始原型的介绍之前,首先来认识一下什么是原型? 在JavaScript中,原型也是一个对象,通过原型可以实现对象的属

JavaScript 权威指南(4): JavaScript 的作用域和提升

JavaScript 权威指南(4): JavaScript 的作用域和提升 原文地址:http://dyy.im/4406.html 你知道下面的 JavaScript 程序执行时会输出什么值吗? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 答案是“10”,吃惊吗?那么下面的可能会真的让你大吃一惊: var a = 1; function b() { a = 10; return;

JavaScript变量作用域和内存问题(js高级程序设计总结)

1,变量 ECMAScript和JavaScript是等同的吗?个人认为是否定的.我的理解是这样的,ECMAScript是一套完整的标准或者说协议,而JavaScript是在浏览器上实现的一套脚本语言.也就是说,ECMAScript是JavaScript的父类标准.JavaScript是ECMAScript的具体实现.所有ECMAScript定义的数据类型或者语言特性实际上都是伪代码的形式规定的.当然如果可以,ECMAScript也可以有服务器实现,单片机实现(不一定恰当).如果说ECMAScr

深入理解javascript系列之序章

从今天开始,博主会对javascript进行深入理解分析并将自己学习到的一些知识分析整理成博文,来让大家一起共同学习和讨论.如果有什么疑问或者建议,可以和博主联系.如果包含什么错误,希望大家可以进行讨论和指导. 该系列是建立在已经基本掌握了javascript中的基础语法,进入更深一步学习的进阶笔记. 该系列目录分为: 深入理解javascript之内存分配 深入理解javascript之null和undefined 深入理解javascript之作用域 深入理解javascript之原型 深入

深入理解javascript作用域系列第四篇——块作用域

× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的代码,比如块作用域.随着ES6的推广,块作用域也将用得越来越广泛.本文是深入理解javascript作用域系列第四篇——块作用域 let for (var i= 0; i<10; i++) { console.log(i); } 上面这段是很熟

深入理解javascript作用域系列第一篇——内部原理

× 目录 [1]编译 [2]执行 [3]查询[4]嵌套[5]异常[6]原理 前面的话 javascript拥有一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量,这套规则被称为作用域.作用域貌似简单,实则复杂,由于作用域与this机制非常容易混淆,使得理解作用域的原理更为重要.本文是深入理解javascript作用域系列的第一篇——内部原理 内部原理分成编译.执行.查询.嵌套和异常五个部分进行介绍,最后以一个实例过程对原理进行完整说明 编译 以var a = 2;为例,说明javasc