今天无论是在浏览器中还是在浏览器外,JavaScript世界正在经历翻天覆地地变化。如果我们谈论脚本加载、客户端的MVC框架、压缩器、AMD、Common.js还有Coffeescript……只会让你的脑子发昏。对于那些已经早就熟知这些技术的人而言,或许很难想象到现在为止还有很多JS开发者还不熟悉这些工具,甚至事实上,他们很可能现在还不想去尝试这些工具。
这篇文章将会介绍一些很基础的JS知识,以及当开发者想要尝试Backbone.js和Ember.js之类的工具之前需要知道一些内容。当你理解了这篇文章中的大部分内容的时候,你会更有信心去学习其他高级JavaScript知识的时候。这篇文章是假设你曾经使用过JavaScript的,所以如果你从没有接触过它,也许你需要先了解下更基础的知识。现在我们开始吧!
模块
有多少人在一个文件中写的JS像下面的代码块一样?(注意:我可没有说内嵌在HTML文件中哦):
Javascript代码
文章图片
- var someSharedValue = https://www.it610.com/article/10;
- var myFunction = function(){ //do something }
- var anotherImportantFunction = function() { //do more stuff }
名字听起来很高大上,不过它的实现其实很简单:
Javascript代码
文章图片
- (function(){
- //do some work
- })();
现在我们知道要怎么写一个匿名函数了,那就来聊聊为什么要使用它吧。在JS中我们都是在和各种作用域之中的函数打交道,所以如果我们想要创建一个作用域,就可以使用函数。匿名函数中的变量和方法的作用域仅仅在匿名函数中,就不会污染全局的命名空间,那么现在还需要考虑的一个问题是,我们要如何从外部取得那些在匿名函数作用域中的变量和方法呢?答案就是全局命名空间:将变量放入全局命名空间中,或者至少将作用变量与全局命名空间关联起来。
想要在匿名函数外部调用方法,我们可以将window对象传入匿名函数,再将函数或变量值赋值到这个对象上。为了保证这个window对象的引入不会造成什么混乱,我们可以将widow对象作为一个变量传入我们的匿名函数。当做函数传入参数的方法同样适用于第三方库,甚至undefined这样的值。现在我们的匿名函数看起来是这样的:
Javascript代码
文章图片
- (function(window, $, undefined){
- //do some work
- })(window, jQuery);
现在我们有了一个会立即执行的方法,还有一个相对安全的执行上下文,其中还包含有window、$和undefined变量(这几个变量还是有可能在这个脚本被执行前就被重新赋值,不过现在的可能性要小的多了)。现在我们已经做得很好了:把我们的代码从全局环境下的一团混乱的局面中拯救了出来;降低了与其他在同一应用中使用的脚本的冲突可能性。
任何我们想要从模块中获取的东西都可以通过window对象拿到。但是通常我不会直接将模块中的内容直接复制到window对象上,而是会用更有组织性地将模块中的内容。在大部分语言中,我们将这些容器称为“命名空间”,在JS中我们可以用“对象”的方式来模拟。
命名空间
如果我们想要声明一个命名空间,将一个函数放进这个空间中,代码可以写成这样:
Javascript代码
文章图片
- window.myApp = window.myApp || {};
- window.myApp.someFunction = function(){
- //so some work
- };
Javascript代码
文章图片
- (function(myApp, $, undefined){
- //do some work
- }(window.myApp = window.myApp || {}, jQuery));
Javascript代码
文章图片
- window.myApp = (function(myApp, $, undefined){
- //do some work
- return myApp;
- })(window.myApp || {}, jQuery);
Javascript代码
文章图片
- MyApp.MyModule.MySubModule.doSomething();
Javascript代码
文章图片
- var MySubModule = MyApp.MyModule.MySubModule;
揭秘模块模式
在创建模块时你也常会看到另一种设计模式:揭秘模块模式(Revealing Module Pattern)。它和模块模式有一些不同:所有定义在模块中的内容都是私有的,然后你可以把所有要暴露到模块外部的内容放在一个对象中,再返回这个对象。你可以这么做:
Javascript代码
文章图片
- var myModule = (function($, undefined){
- var myVar1 = '',
- myVar2 = '';
- var someFunction = function(){
- return myVar1 + " " + myVar2;
- };
- return {
- getMyVar1: function() { return myVar1; }, //myVar1 public getter
- setMyVar1: function(val) { myVar1 = val; }, //myVar1 public setter
- someFunction: someFunction //some function made public
- }
- })(jQuery);
创建构造器(类)
在JS中没有“类”这个概念,但是我们可以通过创建构造器来创建“对象”。假设现在我们要创建一系列Person对象,还需要传入姓、名和年龄,我们可以将构造器定义成下面这样(这部分代码应该放在模块之中):
Javascript代码
文章图片
- var Person = function(firstName, lastName, age){
- this.firstName = firstName;
- this.lastName = lastName;
- this.age = age;
- }
- Person.prototype.fullName = function(){
- return this.firstName + " " + this.lastName;
- };
第二个方法中我们使用了Person构造器的”原型”(prototype)。一个函数的原型就是一个对象,当你需要在某个实例上解析它所调用到的字段或者函数时你需要遍历这个函数上所有的实例。所以这几行代码所做的就是创建一个fullName方法的实例,然后所有的Person的实例都能直接调用到这方法,而不是对每个Person实例都添加一个fullName方法,造成方法的泛滥。我们也可以在构造器中用
Javascript代码
文章图片
- this.fullName = function() { …
如果我们想要创建一个Person实例,我们可以这么做:
Javascript代码
文章图片
- var person = new Person("Justin", "Etheredge");
- alert(person.fullName());
Javascript代码
文章图片
- var Spy = function(firstName, lastName, age){
- this.firstName = firstName;
- this.lastName = lastName;
- this.age = age;
- };
- Spy.prototype = new Person();
- Spy.prototype.spy = function(){
- alert(this.fullName() + " is spying.");
- }
- var mySpy = new Spy("Mr.", "Spy", 50);
- mySpy.spy();
结语
看到这里,希望你已经学到了一些东西。不过这篇文章里并没有介绍多少关于“现代”JS的开发。这篇文章中涉及的还是旧知识,在过去几年里它们的使用面相当广。希望你看完这篇文章以后,找到了学习JS的正确的方向。现在可能你把代码放到了不同的模块不同的文件中(你应该做到这一点!),那么下一步你要开始着手研究如何将JS结合和压缩。如果你是使用Rails 3的开发者,可以在asset pipeline上免费获取这些信息或者工具。如果你是.NET开发者,你可以看看SquishIt框架,我就是从这里开始的。如果你是ASP.NET MVC 4的开发者,也有相关的资源。
希望这篇文章对你有帮助。以后我也会介绍关于现代JS的开发,期待到时候能看到你的ID。
原文链接:codethinked翻译:伯乐在线-kmokidd
译文链接:http://blog.jobbole.com/66135/
推荐阅读
- Javascript自执行匿名函数(function() { })()的原理浅析
- JavaScript|函数有参无参真有很大区别吗()
- Web前端|轻松理解JavaScript匿名函数、自执行函数、闭包函数、回调函数
- JavaScript|JavaScript之匿名函数和闭包
- JavaScript|JavaScript常见数组方法,教你如何转置矩阵
- Web前端|js声明匿名函数
- Vue|Vue组件通信常用的的几种方式
- 浅谈setInterval(aa,1000)与setInterval(aa(),1000)的区别
- java|2022年支付宝集五福|看这里100%扫敬业福