当前位置:编程学习 > JS >>

JS作用域

1.js的作用域是有函数划分的,而不是块儿

        var too="test";

        if(true){//这是在块中的定义,此时还是全局变量
            var too="new test";
        }
        alert(too=="new test");//return true;
        function test()
        {
            var too="old test";//这是在函数中的定义,此时是局部变量

        }

        test();

        alert(too=="new test");//return true;too并没有改变

2.所有属于全局作用域的变量都是window对象的属性

上面例子中 第一行的 too就是等于 window.too

看下面的例子

        function test()
        {
            too="test";
        }
        test();

        alert(window.too="test");

是不是很奇怪,上面例子中函数中的too是局部变量,在这里就是全局变量了

注意下两个例子的区别,一个通过显示声明 var too

一个隐示声明too="test";

也就是说没有显示定义的变量,它就是全局变量,虽然它可能只能在这个函数内使用。

 

作用域(scope)是JavaScript语言的基石之一,在构建复杂程序时也可能是最令我头痛的东西。记不清多少次在函数之间传递控制后忘记 this关键字引用的究竟是哪个对象,甚至,我经常以各种不同的混乱方式来曲线救国,试图伪装成正常的代码,以我自己的理解方式来找到所需要访问的变量。

这篇文章将正面解决这个问题:简述上下文(context)和作用域的定义,分析可以让我们掌控上下文的两种方法,最后深入一种高效的方案,它能有效解决我所碰到的90%的问题。

我在哪儿?你又是谁
JavaScript 程序的每一个字节都是在这个或那个运行上下文(execution context)中执行的。你可以把这些上下文想象为代码的邻居,它们可以给每一行代码指明:从何处来,朋友和邻居又是谁。没错,这是很重要的信息,因为 JavaScript社会有相当严格的规则,规定谁可以跟谁交往。运行上下文则是有大门把守的社区而非其内开放的小门。

我们通常可以把这些社会边界称为作用域,并且有充足的重要性在每一位邻居的易做图里立法,而这个易做图就是我们要说的上下文的作用域链(scope chain)。在特定的邻里关系内,代码只能访问它的作用域链内的变量。与超出它邻里的变量比起来,代码更喜欢跟本地(local,即局部)的打交道。

具体地说,执行一个函数会创建一个不同的运行上下文,它会将局部作用域增加到它所定义的作用域链内。JavaScript通过作用域链的局部向全局攀升方 式,在特定的上下文中解析标识符。这表示,本级变量会优先于作用域链内上一级拥有相同名字的变量。显而易见,当我的好友们一起谈论”Mike West”(本文原作者)时,他们说的就是我,而非bluegrass singer 或是Duke professor, 尽管(按理说)后两者著名多了。

让我们看些例子来探索这些含义:

<script type="text/javascript">
var ima_celebrity = "Everyone can see me! I'm famous!",
the_president = "I'm the decider!";

function pleasantville() {
var the_mayor = "I rule Pleasantville with an iron fist!",
ima_celebrity = "All my neighbors know who I am!";

function lonely_house() {
var agoraphobic = "I fear the day star!",
a_cat = "Meow.";
}
}
</script>
我们的全明星,ima_celebrity, 家喻户晓(所有人都认识她)。她在易做图上积极活跃,敢于在一个相当频繁的基层上叫嚣总统(即the_president)。她会为碰到的每一个人签名和回 答问题。就是说,她不会跟她的粉丝有私下的联系。她相当清楚粉丝们的存在 并有他们自己某种程度上的个人生活,但也可以肯定的是,她并不知道粉丝们在干嘛,甚至连粉丝的名字都不知道。

而在欢乐市(pleasantville)内,市长(the_mayor)是众所周知的。她经常在她的城镇内散步,跟她的选民聊天、握手并亲吻小孩。因为 欢乐市(pleasantville)还算比较大且重要的邻居,市长在她办公室内放置一台红色电话,它是一条可以直通总统的7×24热线。她还可以看到市 郊外山上的孤屋(lonely_house),但从不在意里面住着的是谁。

而孤屋(lonely_house)是一个自我的世界。旷恐患者时常在里面囔囔自语,玩纸牌和喂养一个小猫(a_cat)。他偶尔会给市长 (the_mayor)打电话咨询一些本地的噪音管制,甚至在本地新闻看到ima_celebrity后会写些粉丝言语给她(当然,这是 pleasantville内的ima_celebrity)。

this? 那是虾米?
每一个运行上下文除了建立一个作用域链外,还提供一个名为this的关键字。它的普遍用法是,this作为一个独特的功能,为邻里们提供一个可访问到它的 途径。但总是依赖于这个行为并不可靠:取决于我们如何进入一个特定邻居的具体情况,this表示的完全可能是其他东西。事实上,我们如何进去邻居家本身, 通常恰恰就是this所指。有四种情形值得特别注意:

呼叫对象的方法
在经典的面向对象编程中,我们需要识别和引用当前对象。this极好地扮演了这个角色,为我们的对象提供了自我查找的能力,并指向它们本身的属性。

<script type="text/javascript">
var deep_thought = {
the_answer: 42,
ask_question: function () {
return this.the_answer;
}
};

var the_meaning = deep_thought.ask_question();
</script>

这个例子建立了一个名为deep_thought的对象,设置其属性 the_answer为42,并创建了一个名为ask_question 的方法(method)。当deep_thought.ask_question()执行时, JavaScript为函数的呼叫建立了一个运行上下文,通过”.“运算符把this指向被引用的对象,在此是deep_thought这个对象。之后这 个方法就可以通过this在镜子中找到它自身的属性,返回保存在 this.the_answer中的值:42。

构造函数
类似地,当定义一个作为构造器的使用new关键字的函数时,this可以用来引用刚创建的对象。让我们重写一个能反映这个情形的例子:

<script type="text/javascript">
function BigComputer(answer) {
this.the_answer = answer;
this.ask_question = function () {
return this.the_answer;
}
}

var deep_thought = new BigComputer(42);
var the_meaning = deep_thought.ask_question();
</script>

我们编写一个函数来创建BigComputer对象,而不是直白地创建 deep_thought对象,并通过new关键字实例化deep_thought为一个实例变量。当new BigComputer()被执行,后台透明地创建了一个崭新的对象。呼叫BigComputer后,它的this关键字被设置为指向新对象的引用。这个 函数可以在this上设置属性和方法,最终它会在BigComputer执行后透明地返回。

尽管如此,需要注意的是,那个deep_thought.the_question()依然可以像从前一样执行。那这里发生了什么事?为何this在 the_question内与BigComputer内会有所不同?简单地说,我们是通过new进入BigComputer的,所以this表示“新 (new)的对象”。在另一方面,我们通过 deep_thought进入the_question,所以当我们执行该方法时,this表示 “deep_thought所引用的对象”。this并不像其他的变量一样从作用域链中读取,而是在上下文的基础上,在上下文中重置。

函数呼叫
假如没有任何相关对象的奇幻东西,我们只是呼叫一个普通的、常见的函数,在这种情形下this表示的又是什么呢?

<script type="text/javascript">
function test_this() {
return this;
}
var i_wonder_what_this_is = test_this();
</script>

在这样的场合,我们并不通过new来提供上下文,也不会以某种对象形式在背后偷偷提供上下文。在此, this默认下尽可能引用最全局的东西:对于网页来说,这就是 window对象。

事件处理函数
比普通函数的呼叫更复杂的状况,先假设我们使用函数去处理的是一个onclick事件。当事件触发我们的函数运行,此处的this表示的是什么呢?不凑巧,这个问题不会有简单的答案。

如果我们写的是行内(inline)事件处理函数,this引用的是全局window对象:

<script type="text/javascript">
function click_handler() {
alert(this); // 弹出 window 对象
}
</script>
...
<button id=

补充:web前端 , JavaScript ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,