资讯专栏INFORMATION COLUMN

【译】理解JavaScript:作用域

betacat / 2838人阅读

摘要:作用域是代码的不同部分在运行期间的可见性。大多数开发者想当然地理解作用域,但毫无疑问,有它自己的说明。变量可能是全局作用域的,或者是方法作用域的。总而言之,不要重复声明变量,使用良好命名,尽力避免在声明前调用和执行任何东西。

原文链接:https://hackernoon.com/unders...

什么是作用域?

就像JavaScript中的其他东西一样,作用域并无特别之处。尽管大多数开发者并不会在上面太多时间,不过,深入理解作用域有助于你写更干净的应用,也有助于降低错误和实现更好的设计模式。

作用域是代码的不同部分在运行期间的可见性。

大多数开发者想当然地理解作用域,但毫无疑问,JavaScript有它自己的说明。变量可能是全局作用域的,或者是方法作用域的。这也就意味着,变量存在于任何地方都能被访问的全局,或者存在于声明它们的方法之内。

var global = "I am global scoped"

function testingFunctionScope() {
    var global = "I am function scoped";
    console.log(global); // I am function scoped
}

testingFunctionScope(); 
console.log(global); // I am global scoped

正如你在例子中看到的那样,尽管全局变量在方法内被赋予一个不同的值,但它只保存在这个方法中。在方法外面,那个变量有一个不同的值---在全局作用域声明的值。

var global = "global"
var anotherGlobal = "also global"

function functionScope () {

    var global = "function scope"
    console.log(global) // function scope
    var scoped = "also function scope"

    function inner () {
        console.log(scoped); // also function scope
        console.log(anotherGlobal) // also global
    }

    inner();

}

console.log(global) // global
console.log(anotherGlobal) // also global
console.log(scoped) // ReferenceError

functionScope();
inner(); // ReferenceError

这是一个拥有内部函数的例子,并展示了它如何访问父作用域的变量。正如父函数 functionScope()那样 ,它内部声明的每个变量只在其内部和它的内部函数中有效。

注意:绝对不要使用未声明的变量 如果那样做了,引擎会冒泡到父作用域寻找此变量。如果寻之不得,js会为你声明一个。这样你无意之中就创建了一个全局变量并扰乱了全局作用域。

另外,未定义和未声明不是同一件事情。未定义:声明了一个变量但没有赋值,未声明:变量根本还没有被声明。

好了,到目前为止,没有什么特别之处,且看下面代码如何返回:

test(); // ???
function test() {
  console.log("working?!");
}

惊不惊喜?确实打印出了 working?!。为了理解其中缘由我们必须探求JavaScript另一个概念。

变量提升

在此我将不同于他人,我会描述什么是变量提升并解释其弊端。困惑?好-Javascript就应该困惑。变量提升这种奇怪的行为,意味着你可以在方法声明前调用它。

在JavaScript中,代码执行之前变量和方法会被移至顶端。所以上面奇怪的代码判断,实际上变成:

function test() {
  console.log("working?!");
}
test(); // working?!

因此,我们写的和实际执行的并不一致。变量定义也是一样---它们都会提升到自己作用域的顶部(用var关键字声明的会;用let声明的则不会)。变量的声明会提升,赋值并不会。所以如果我们在一个变量赋之前使用它,得到的是undifined,并不是错误

var test;
console.log(test) // undefined
test = "working?"
console.log(test) // working?

所以使用函数表达式的时候千万小心,因为只有函数的声明提升了。我们现在对JavaScript中的的作用域和变量提升有了基本的理解,实际上两者有很大不同。JS代码的整个执行过程非常不同,并且变量提升也并非大多说人所想。这更多的是我们持有的精神概念。

编译

出乎意料,JavaScript确实需要编译。V8引擎在执行前通过将JavaScript编译成本地机器码而不是执行字节码或解释它来提升性能。实际上引擎会多线程运行代码。其中一个线程,负责声明所有方法和变量,所以在运行时都已存在。虽然解释编译过程更加简单,对于变量提升我们创建了在代码运行前如何组织代码的思维导图。

简言之---在JS代码实际执行前,引擎已经运行了整个脚本并在它们的作用域中声明了所有的变量和方法。所以在运行时,它们已经存在,变量提升并非什么黑魔法。如果你理解了这个,你就超过了其他90%的JavaScript开发者。

总结

JavaScript的作用域还有很多需要学习。为了缩短篇幅让大家有个基本的理解,我甚至都没有提LHS和RHS。如果你搞不清楚你所做的事情,JavaScript绝对惊喜多多(bug啊)。总而言之,不要重复声明变量,使用良好命名,尽力避免在声明前调用和执行任何东西。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94971.html

相关文章

  • 理解JavaScript:闭包

    摘要:当面试中让我解释一下闭包时我懵逼了。这个解释开始可能有点晦涩,让我们抽丝剥茧摘下闭包的真面目。此文不详述作用域有专门的主题阐述,不过作用域是理解闭包原理的基础。这才是闭包的真正便利之处。闭包使用不当就会很坑。 原文链接 为什么深度学习JavaScript? JavaScript如今是最流行的编程语言之一。它运行在浏览器、服务器、移动设备、桌面应用,也可能包括冰箱。无需我举其他再多不相干...

    岳光 评论0 收藏0
  • 】《精通使用AngularJS开发Web App》(三)--- 深入scope,继承结构,事件系

    摘要:比如,我们可以监听事件由实例发出,然后在任何浏览器中就是变化的时候都会得到通知,如下所示每一个作用域对象都会有这个方法,可以用来注册一个作用域事件的侦听器。这个函数所扮演的侦听器在被调用时会有一个对象作为第一个参数。 上一篇:【译】《精通使用AngularJS开发Web App》(二) 下一篇:【译】《精通使用AngularJS开发Web App》(四) 书名:Mastering W...

    wind5o 评论0 收藏0
  • [] 你想知道的关于 JavaScript 作用的一切

    摘要:原文链接原文作者你想知道的关于作用域的一切译中有许多章节是关于的但是对于初学者来说甚至是一些有经验的开发者这些有关作用域的章节既不直接也不容易理解这篇文章的目的就是为了帮助那些想更深一步学习了解作用域的开发者尤其是当他们听到一些关于作用域的 原文链接: Everything you wanted to know about JavaScript scope原文作者: Todd Mott...

    Flands 评论0 收藏0
  • :用let 和 const 来指导JavaScript 的变量提升

    摘要:最近在上看到一篇关于变量提升的文章,原文在此。对于刚入门的开发者时常难以理解变量方法提升的独特行为。接下来我们要谈论,,声明,那么先了解变量提升就显得更为重要了。在进入作用域和不能访问的这段时间,我们称为暂时性死区。 showImg(https://segmentfault.com/img/bV0Nsd?w=800&h=450); 最近在Medium上看到一篇关于变量提升的文章,原文在...

    sanyang 评论0 收藏0
  • 】this 是什么?JavaScript 对象的内部工作原理

    摘要:关键字会实例化一个新的对象实例,并在执行构造函数时将指向该实例。原文链接译是什么对象的内部工作原理 原文链接:What is this? The Inner Workings of JavaScript Objects (需要梯子) 原文作者:Eric Elliott 译文永久链接:【译】什么是 this?JavaScript 对象的内部工作原理 译者:士心 翻译目的:函数动...

    Hwg 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<