全局变量

javaScript通过函数管理变量作用域。在函数内部声明的变量只在这个函数内部可用,函数外面不可用。另一方面,在任何函数外面声明的或是函数内未声明直接使用的变量叫做全局变量。

每个JavaScript环境有一个全局对象,当你在任意的函数外面使用this的时候可以访问到。你创建的每一个全局变量都成了这个全局对象的属性。

在浏览器中,全局对象有个附加属性叫做window,它表示浏览器的窗口,所有函数和全局变量均自动成为window的成员。下面的代码片段显示了如何在浏览器环境中创建和访问的全局变量:

myglobal = "hello"; // 不推荐写法
console.log(myglobal); // "hello"
console.log(window.myglobal); // "hello"
console.log(window["myglobal"]); // "hello"
console.log(this.myglobal); // "hello"

全局变量的问题在于,你的JavaScript应用程序和web页面上的所有代码都共享了这些全局变量,他们住在同一个全局命名空间,所以当程序的两个不同部分定义同名但不同作用的全局变量的时候,命名冲突在所难免。

web页面包含不是该页面开发者所写的代码也是比较常见的,例如:

  • 第三方的JavaScript库
  • 广告方的脚本代码
  • 第三方用户跟踪和分析脚本代码
  • 不同类型的小组件,标志和按钮

比方说,该第三方脚本定义了一个全局变量,叫做result;接着,在你的函数中也定义一个名为result的全局变量。其结果就是后面的变量覆盖前面的,第三方脚本就会失去效果!

因此,要想和其他脚本成为好邻居的话,尽可能少的使用全局变量是很重要的。后面会提到的一些减少全局变量的策略,例如命名空间模式或是函数立即自动执行,但是要想让全局变量少最重要的还是始终使用var来声明变量。

由于JavaScript的两个特征,不自觉地创建出全局变量是出乎意料的容易。首先,你可以甚至不需要声明就可以使用变量;第二,JavaScript有隐含的全局概念,意味着你不声明的任何变量都会成为一个全局对象属性。参考下面的代码:

function sum(x, y) {
   // 不推荐写法: 隐式全局变量
   result = x + y;
   return result;
}

此段代码中的result没有声明。代码照样运作正常,但在调用函数后你最后的结果就多一个全局变量,这可以是一个问题的根源。经验法则是始终使用var声明变量,正如改进版的sum()函数所演示的:

function sum(x, y) {
   var result = x + y;
   return result;
}

隐式全局变量和明确定义的全局变量间有些小的差异,就是通过delete操作符让变量未定义的能力。

  • 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。
  • 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。

这表明,在技术上,隐式全局变量并不是真正的全局变量,但它们是全局对象的属性。属性是可以通过delete操作符删除的,而变量是不能的:

// 定义三个全局变量
var global_var = 1;
global_novar = 2; // 反面教材
(function () {
   global_fromfunc = 3; // 反面教材
}());

// 试图删除
delete global_var; // false
delete global_novar; // true
delete global_fromfunc; // true

// 测试该删除
typeof global_var; // "number"
typeof global_novar; // "undefined"
typeof global_fromfunc; // "undefined"

函数作用域和声明提前

在类似c语言的编程语言中,花括号({})内的每一段代码都具有自己的各自作用域,而且变量声明在他们的代码段之外是不可见的,我们称之为块级作用域。js中则没有块级作用域。去而待之的是函数作用域,变量在声明它的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

如下代码中:在不同的位置定义了变量i、j、和k,它们都在同一个作用域内——这三个变量在函数体内均是有定义的:

function test(o){
    var i=0;
    if(typeof o=="object"){
        var j=0;
        for(var k=0; k<10; k++){
            console.log(k);
        }
        console.log(k);
    }
    console.log(j);
}

javascript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的。有意思的是,这意味着变量在变量在声明之前甚至已经可用。javascript的这个特性被非正式的称为“声明提前”:即javascript函数里声明了所有的变量(但不涉及赋值)都被”提前“至函数体的顶部。
如下代码:

var scope = "global";
function f(){
    console.log(scope);
    var scope="local";
    consloe.log(scope);
}

你可能误以为函数的第一行会输出“global”,因为代码还没有执行到var语句声明局部变量的地方,其实不然,由于函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,在函数体内局部变量遮盖了同名的全局变量。尽管如此,只有在程序执行到var语句的时候,局部变量才会真正地赋值。因此,上述过程等价于:将函数内的变量声明“提前”至函数体顶部,同时变量初始化留在原来的位置:
代码:

function f(){
    var scope;
    console.log(scope);
    scope="local";
    console.log(scope);
}

在具有块级作用域的编程语言中,在狭小的作用域里让变量声明和使用变量的代码尽可能靠近彼此,通常来讲,这是个非常不错的编程习惯。由于javascript没有块级作用域,因此一些程序员特意将变量声明放在函数体顶部,不是声明在靠近使用变量之处。这种做法是得他们的源代码非常清晰地反映了真实的变量作用域。

命名规范

对于构造函数,可以使用大驼峰式命名法(upper camel case),如MyConstructor()。对于方法名称和变量,你可以使用小驼峰式命名法(lower camel case),像是myFunction(), calculateArea()getFirstName()

JavaScript中没有定义常量的方法(尽管有些内置的像Number, MAX_VALUE),所以开发者都采用全部单词大写的规范来命名这个程序生命周期中都不会改变的变量,如:

// 珍贵常数,只可远观
var PI = 3.14,
    MAX_WIDTH = 800;

还有另外一个完全大写的惯例:全局变量名字全部大写。全部大写命名全局变量可以加强减小全局变量数量的实践,同时让它们易于区分。

另外一种使用规范来模拟功能的是私有成员。虽然可以在JavaScript中实现真正的私有,但是开发者发现仅仅使用一个下划线前缀来表示一个私有属性或方法会更容易些。考虑下面的例子:

var person = {
    getName: function () {
        return this._getFirst() + ' ' + this._getLast();
    },

    _getFirst: function () {
        // ...
    },
    _getLast: function () {
        // ...
    }
};

编写高质量JavaScript代码的基本要点的更多相关文章

  1. 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点

    深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 2011-12-28 23:00 by 汤姆大叔, 139489 阅读, 119 评论, 收藏, 编辑 才华横溢的 ...

  2. 编写高质量JavaScript代码的基本要点记录

    原文:深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 1.最小全局变量(Minimizing Globals)的重要性 JavaScript通过函数管理作用域.在 ...

  3. <深入理解JavaScript>学习笔记(1)_编写高质量JavaScript代码的基本要点

    注:本文是拜读了 深入理解JavaScript 之后深有感悟,故做次笔记方便之后查看. JQuery是一个很强大的JavaScript 类库,在我刚刚接触JavaScript的就开始用了. JQuer ...

  4. 高质量JavaScript代码书写基本要点

    翻译-高质量JavaScript代码书写基本要点 by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/ ...

  5. 编写高质量JavaScript代码的68个有效方法

    简介: <Effective JavaScript:编写高质量JavaScript代码的68个有效方法>共分为7章,分别涵盖JavaScript的不同主题.第1章主要讲述最基本的主题,如版 ...

  6. 高质量JavaScript代码书写基本要点学习

    高质量JavaScript代码书写基本要点学习 可维护的代码意味着: •可读的 •一致的 •可预测的 •看上去就像是同一个人写的 •已记录   最小全局变量(Minimizing Globals)   ...

  7. [转] 翻译-高质量JavaScript代码书写基本要点 ---张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1173 原文作者:St ...

  8. 编写高质量JavaScript代码绳之以法(The Essentials of Writing High Quality JavaScript)翻译

    原文:The Essentials of Writing High Quality JavaScript 才华横溢的Stoyan Stefanov,在他写的由O'Reilly初版的新书<Java ...

  9. 如何编写高质量JavaScript代码

    书写可维护的代码(Writing Maintainable Code ) 软件bug的修复是昂贵的,并且随着时间的推移,这些bug的成本也会增加,尤其当这些bug潜伏并慢慢出现在已经发布的软件中时.当 ...

随机推荐

  1. GridView布局,自定义适配器,水平滚动

    添加GridItem布局XML文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...

  2. C#窗体WinForm 文件操作

    文件及文件夹操作 C/S:WinForm可以操作客户端文件 Client ServerB/S:浏览器服务 Brower Server 命名空间:using system .IO; 1. File类:文 ...

  3. LeetCode: Nim Game

    这题其实不太好想,用到了博弈论 1,2,3 能赢 4 输 5,6,7 赢 8 输 9,10,11 赢 12 输 那么结论就是4的倍数就是输,其他情况就能赢. 为什么会是这样呢?很好解释,根源就在4会输 ...

  4. 面试:浅谈tcp/udp

    tcp是一种面向连接的.可靠的.基于字节流的传输层通信协议.是专门为了在不可靠的互联网络上提供一个可靠的端到端字节流而设计的,面向字节流. udp(用户数据报协议)是iso参考模型中一种无连接的传输层 ...

  5. css字体样式(Font Style),属性

    css字体样式(Font Style),属性   css字体样式(Font Style)是网页中不可或缺的样式属性之一,有了字体样式,我们的网页才能变得更加美观,因此字体样式属性也就成为了每一位设计者 ...

  6. HTML5 webSQL 中查询结果集 result.rows.item 的用法

    加入查询回调函数如下: function(tx,result){ var len = result.rows.length; var recordset = result.rows.item; ){ ...

  7. php curl的使用

    我们来采集一个页面,通常情况下,我们会使用file_get_contents()函数来获取: <?php $str = file_get_contents('http://www.baidu.c ...

  8. asp.net 分页-自己写分页控件

    去年就发表过asp.net 分页-利用后台直接生成html分页 ,那种方法只是单纯的实现了分页,基本不能使用,那时就想写个自己的分页控件,无奈能力有限.最近有点时间了,就自己做出了这个分页控件.我承认 ...

  9. Robotlegs框架1.5简介

    该框架的1.5版本位于https://github.com/robotlegs/robotlegs-framework/tree/version1,现在已经出了重新架构的2.0版本,所以我决定先研究已 ...

  10. Python数据分析之pandas学习

    Python中的pandas模块进行数据分析. 接下来pandas介绍中将学习到如下8块内容:1.数据结构简介:DataFrame和Series2.数据索引index3.利用pandas查询数据4.利 ...