javascript命名空间简介和几种写法

编程语言及工具

99人已加入

描述

  JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。

  JavaScript脚本语言具有以下特点:

  (1)脚本语言。JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。

  (2)基于对象。JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。

  (3)简单。JavaScript语言中采用的是弱类型的变量类型,对使用的数据类型未做出严格的要求,是基于Java基本语句和控制的脚本语言,其设计简单紧凑。

  (4)动态性。JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。在访问一个网页时,鼠标在网页中进行鼠标点击或上下移、窗口移动等操作JavaScript都可直接对这些事件给出相应的响应。

  (5)跨平台性。JavaScript脚本语言不依赖于操作系统,仅需要浏览器的支持。因此一个JavaScript脚本在编写后可以带到任意机器上使用,前提上机器上的浏览器支 持JavaScript脚本语言,目前JavaScript已被大多数的浏览器所支持。

  不同于服务器端脚本语言,例如PHP与ASP,JavaScript主要被作为客户端脚本语言在用户的浏览器上运行,不需要服务器的支持。所以在早期程序员比较青睐于JavaScript以减少对服务器的负担,而与此同时也带来另一个问题:安全性。

  而随着服务器的强壮,虽然程序员更喜欢运行于服务端的脚本以保证安全,但JavaScript仍然以其跨平台、容易上手等优势大行其道。同时,有些特殊功能(如AJAX)必须依赖Javascript在客户端进行支持。随着引擎如V8和框架如Node.js的发展,及其事件驱动及异步IO等特性,JavaScript逐渐被用来编写服务器端程序。

  javascript

  JavaScript中创建命名空间的几种写法

  在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子:

  var sayHello = function() {

  return ‘Hello var’;

  };

  function sayHello(name) {

  return ‘Hello function’;

  };

  sayHello();

  最终的输出为

  》 “Hello var”

  为什么会这样,根据 StackOverFlow 的解释,实际上JavaScript的是按如下顺序解析的。

  function sayHello(name) {

  return ‘Hello function’;

  };

  var sayHello = function() {

  return ‘Hello var’;

  };

  sayHello();

  不带var的function声明被提前解析了,因此现代的JS写法建议你始终使用前置var声明所有变量;

  避免全局变量名冲突的最好办法还是创建命名空间,下面是在JS中合建命名空间的几种常用方法。

  通过函数(function)创建

  这是一种比较常见的写法,通过声明一个function实现,函数里设置初始变量,公共方法写入prototype,如:

  var NameSpace = window.NameSpace || {};

  /*

  Function

  */

  NameSpace.Hello = function() {

  this.name = ‘world’;

  };

  NameSpace.Hello.prototype.sayHello = function(_name) {

  return ‘Hello ’ + (_name || this.name);

  };

  var hello = new NameSpace.Hello();

  hello.sayHello();

  这种写法比较冗长,不利于压缩代码(jQuery使用fn代替prototype),而且调用前需要先实例化(new)。使用Object写成JSON形式可以写得紧凑些:

  通过JSON对象创建Object

  /*

  Object

  */

  var NameSpace = window.NameSpace || {};

  NameSpace.Hello = {

  name: ‘world’

  , sayHello: function(_name) {

  return ‘Hello ’ + (_name || this.name);

  }

  };

  调用

  NameSpace.Hello.sayHello(‘JS’);

  》 Hello JS;

  这种写法比较紧凑,缺点是所有变量都必须声明为公有(public)的,导致所有对这些变量的引用都需要加this指示作用域,写法也略有冗余。

  通过闭包(Closure)和Object实现

  在闭包中声明好所有变量和方法,并通过一个JSON Object返回公有接口:

  var NameSpace = window.NameSpace || {};

  NameSpace.Hello = (function() {

  //待返回的公有对象

  var self = {};

  //私有变量或方法

  var name = ‘world’;

  //公有方法或变量

  self.sayHello = function(_name) {

  return ‘Hello ’ + (_name || name);

  };

  //返回的公有对象

  return self;

  }());

  Object和闭包的改进型写法

  上个例子在内部对公有方法的调用也需要添加self,如:self.sayHello(); 这里可以最后再返回所有公有接口(方法/变量)的JSON对象。

  var NameSpace = window.NameSpace || {};

  NameSpace.Hello = (function() {

  var name = ‘world’;

  var sayHello = function(_name) {

  return ‘Hello ’ + (_name || name);

  };

  return {

  sayHello: sayHello

  };

  }());

  Function的简洁写法

  这是一种比较简洁的实现,结构紧凑,通过function实例,且调用时无需实例化(new),方案来自stackoverflow:

  var NameSpace = window.NameSpace || {};

  NameSpace.Hello = new function() {

  var self = this;

  var name = ‘world’;

  self.sayHello = function(_name) {

  return ‘Hello ’ + (_name || name);

  };

  };

  调用

  NameSpace.Hello.sayHello();

  javascript模块与命名空间的介绍

  模块化的目标是支持大规模的程序开发,处理分散源中代码的组装,并且能让代码正确运行,哪怕包含了不需要的模块代码,也可以正确执行代码。

  理想状态下,所有模块都不应当定义超过一个全局标识。

  模块函数

  通过把模块定义在某个函数的内部来实现,定义的变量和函数都属于该函数的局部变量,在函数外不可见。实际上,可以将这个函数作用域用做模块的命名空间(模块函数)

  一旦将模块代码封装进一个函数中,就需要一些方法导出公用API,以便在模块函数外部调用它们。下面有几种方式导出公用API:

  首先创建一个命名空间

  代码如下:

  // 创建一个全局变量用来存放与学校相关的模块

  var school; // 创建school命名空间

  if(!school) school = {};

  1. 利用构造函数

  代码如下:

  // 返回Student构造函数来导出公共API

  school.Student = (function() {

  function Student() {

  }

  // 。。。。。。 定义Student的原型对象和私有属性和方法 。。。。。。。。

  return Student; // 返回Student构造方法导出公共API

  })();

  2. 返回命名空间对象

  如果模块API包括多个单元,则它可以返回命名空间对象

  代码如下:

  // 为school添加students模块

  school.students = (function() {

  // 这里定义了很多类如课程类/成绩类, 使用局部变量和函数

  function Subject() { /* 。。。 */ }

  function Grade() { /* 。。。 */ }

  // 通过返回命名空间对象将API导出

  return {

  Subject: Subject,

  Grade: Grade

  };

  })();

  3. 通过关键字new调用

  另外一种类似类似技术:把模块函数当做构造函数,通过new来调用。把它们(公共API)赋值给this属性来将其导出

  代码如下:

  school.students = (new function() {

  // 。。。。。 这里省略了代码 。。。。。。

  // 将API导到this对象中

  this.Subject = Subject;

  this.Grade = Grade;

  // 注意,这里没有返回值

  }()); // 括号写在里面。这里是创建新实例,new后面应紧跟构造函数的调用而不是表达式

  4. 已定义命名空间对象

  作为一种替代方案,如果已经定义了全局命名空间对象,通过模块函数可以直接设置那个对象的属性。

  代码如下:

  // 如果已经定义了命名空间对象

  var school; // 创建school命名空间

  if(!school) school = {};

  school.students = {}; // student命名空间已经定义

  (function(students) {

  // 。。。。。 这里省略了代码 。。。。。。

  // 将公共API导到上面定义的命名空间中

  students.Subject = Subject;

  students.Grade = Grade;

  // 这里也不需要返回值

  })(school.students);

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分