源栈培训:JavaScript-3:作用域

更多
2019年04月18日 20点44分 作者:叶飞 修改

函数作用域(scope)

如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量。

不同函数内部的同名变量互相独立,互不影响。

JavaScript的函数可以嵌套(为什么要嵌套?),且内部函数可以访问外部函数(的实参和变量,见:词法作用域)。

        function outFunc(name) {
            var age = 100;
            function innerFunc() {
                alert(age);   //age定义在innerFunc()之外
            }
            innerFunc();
        }

如果内部函数中的变量和外部函数中的变量重名?(演示:注意“有var”和“没有var”)

作用域链:由内向外查找,直到undefined。


变量提升

猜一猜,调用下面的函数会发生什么?

function greet() {
    var greet = 'Hello, ' + name;  //y没有声明就使用,会报错么?
    console.log(x);
    var name = '飞哥';
}

JavaScript解释器在解释执行时,会先扫描整个函数体的语句,把所有声明的变量“提升”到函数顶部。(我倾向于认为是到作用域中“查找”

注意:提升的仅仅是变量的声明,不包括变量的赋值。

所以,和其他语言(如C#)不同,JavaScript不提倡“就近声明”,而是提倡“(用一个var)函数开头就声明全部变量”:

  • 增加代码的可读性
  • 避免变量名冲突

思考:函数也是变量(复习:将匿名函数赋值给变量),那么,函数和函数变量是不是也可以“提升”?


词法作用域

通过以下代码:

        var name = "飞哥";
        function smart() {
            //var name = '子祥';        
            alert(`${name}最帅`);
        }
        //smart();

        function reallySmart() {
            var name = '子祥';
            smart();
        }
        reallySmart();

理解:由var声明的变量,其作用域由是由其代码写在哪里(不是在哪里执行)决定的。


块级作用域(ES6)

猜一猜这段代码的执行结果:

        function blockScope() {
            if (true) {
                var i = 986; 
            }
            console.log('i=' + i);
        }
        blockScope();
哪里不对劲呢?

JavaScript没有“块级(block)”作用域。直到ES6,才引入了关键字:let。由let声明的变量,具有块级作用域(推荐使用)。

同时引入的,还有关键字:const,用于声明常量。


全局变量

花絮:这name是特么哪里来的?

不在任何函数内定义的变量就具有全局作用域。

实际上,

  • 全局变量是window的属性
  • 顶层函数是window的方法

可耻的“名称冲突”:

  • 如果script只是在HTML页面中使用,全局变量还可以接受(而且比较方便)
  • 但随着JavaScript规模扩大,一个项目可能引用多个类库(js文件),名称冲突就越来越难以避免,给调试带来极大的问题!


模拟名称空间(namespace)

  1. 先定义一个唯一的全局变量(对象)
  2. 其他变量都写出是上述全局变量的成员(属性和方法)
  3. 还可以多层嵌套,最后形成名称空间一样的“样式”

JQuery等类库就是这样做的。但仍然不能完全避免名称冲突(参考:JQuery的noConflict() 方法


strict模式(ES5)

如果在JavaScript的函数中声明变量,不使用var,该变量就具有全局作用域(最坑爹!)

在JavaScript代码的第一行写上:

'use strict';  -- 如果浏览器不支持?

使用严格模式,就能强制JavaScript声明变量时必须使用:var。否则会报错(注意:浏览器默认不会将JavaScript的报错显示给客户,一般需要在调试窗口才能看到



在C#中我们都基本上不讲作用域,因为一切都是自然而然的(用语言描述反而有些困难)。但JavaScript的作用域,让人非常头大!

你以为这样就结束了?too young too simple啊!作为一个“先天严重不足,后天各种补丁”的语言,这一切才刚刚开始……


作业

在函数yz.fei.get986()中嵌入不带参数的函数has9()/has8()/has6(),并调用上述函数,找出10000以内有多少个数字包含:9或者8或者6。



源栈 JavaScript 入门 作用域
赞: 0 踩: 0

打赏
已收到打赏的 帮帮币

你的 打赏 非常重要!
为了保证文章的质量,每一篇文章的发布,都已经消耗了作者 1 枚 帮帮币
没有“帮帮币”,作者无法发布新的文章。

全系列阅读
评论 / 0
叶飞的系列文章

源栈培训:ASP.NET全栈开发

飞哥的源栈培训:线上全程直播,免费收看;线下拎包入住,按周计费。本系列收录所有讲义(含视频录播地址)

编程那些事:菜鸟入门

大飞哥倾力之作,面向有意入行IT/开发/编程的初学者,欢迎任何形式的留言建议……

从包工头到程序猿

真实故事,讲述我在家装公司关门之后,如何转行成为一个程序猿的故事。(《折腾》第三卷)

《折腾》(卷一)青涩

时间段:从大学毕业到开始创业。离开青葱校园,涉世之初的那些往事……

《折腾》(卷二)风雨 之(1)工地

我一个完全的门外汉(无论装修还是管理),开始给黎叔装修房子。从踌躅满志,到四处碰壁;从一往直前,到左右为难……

《折腾》(卷二)风雨 之(2)胸怀

作为一个律师,接工程没签合同,被狠狠的坑了一把!年轻人暴烈的想要复仇,黎叔教他一个企业家的胸怀……

《折腾》(卷二)风雨 之(3)渠道

成立了公司,招聘了员工,开始大力的拓展业务,一个接一个的坑,摔倒了又爬起来……

《折腾》(卷二)风雨 之(4)视野

经历残酷现实的磨砺,终于明白:干啥事,都不能闭门造车,人要走出去,开阔视野……

未分类

系统自动生成的未分类系列

一锅大杂烩

从律师到包工头,从码农到写手,读书交友生活创业,各种零零碎碎,乱七八糟……

人人都是程序猿

计算机编程普及课程,视频:https://space.bilibili.com/55410301/#/channel/detail?cid=49491

全部
关键字



帮助

反馈