全局变量

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. thttpd和cgilua安装与运行流程分析

    安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...

  2. RDIFramework.NET开发实例━表约束条件权限的使用-Web

    RDIFramework.NET开发实例━表约束条件权限的使用-Web 在上一篇文章“RDIFramework.NET开发实例━表约束条件权限的使用-WinForm”我们讲解了在WinForm下表约束 ...

  3. linux下用户账户切换

    1,)当前我已经登录一个用户hadoop,我怎么切换到root账户呢(应为一般用户经常会遇到无权限修改/etc/hosts./ect/hostname等文件的权限)? 使用命令sudo su root ...

  4. 【Unity3D基础】让物体动起来①--UGUI鼠标点击移动

    背景 首先还是先声明自己是比较笨的一个人,总是找不到高效的学习方法,目前自己学习Unity3D的方式主要是两种,一种是直接看高质量的源码,另一种是光看不行还要自己动手,自己写一些有代表性的小程序,这也 ...

  5. LATEX论文排版学习资源汇总

    一.国内出版的LaTeX书籍 不管是ctex还是chinatex论坛,很多TeX前辈和使用者都给大家提供了很多咨询帮助,同时,也分享了很多很多学习上的方法与技巧.一般都推荐入门的用户先阅读一本入门书, ...

  6. matlab中动态绘图并保存为视频的小例子

    如题,多的就不说了,先上一个效果: 每隔0.1秒,绿色的直线转动一个角度. 再看看代码如何实现: fuction main clear; clc; %%%%%%%%%%%%%%%%%%%%%%%%%% ...

  7. java多态性

    多态分两种: (1)   编译时多态(设计时多态):方法重载. (2)   运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态.(我们平时说得多的事运行时 ...

  8. Android——初探Dagger2依赖注入

    1,在做项目时,经常需要在一个对象里去创建另一个对象的示例,这种行为是产生耦合的常见形式,对于一个大型项目来说,过多的相互依赖会导致代码难以维护,很容易就会碰到修改一个小需求需要大面积的修改各种代码, ...

  9. Oracle 流复制实践笔记

    最近因为业务需求,需要在两个数据库之间做双向实时同步,遂实践了一把Oracle的流复制,遇到了很多疑难问题,最终也貌似成功,现记录如下. 我是使用OEM来实现流复制的. 10.进行流复制的两个数据库的 ...

  10. Asp.net 之Application

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...