面向对象的Javascript之一(初识Javascript)


Posted in Javascript onJanuary 20, 2012

1. Javascript最大的特性在于其灵活性。作为一名前端开发人员,既可以采用函数式的编程风格,也可以采用更复杂一点的面向对象的编程风格。不管你采用哪种风格,都可以完成一些非常有用的任务。因而,Javascript是一门面向过程的语言,同时也是一门面向对象的语言,进而可以模仿面向对象语言的编程模式和惯用法。我们用一个例子来说明:启动和停止动画。

如果你习惯于函数式的编程风格,代码会如下:

function startAnimation() { 
//启用动画 
} 
function stopAnimation() { 
//停止动画 
}

这种方法很简单,但却无法创建保存状态以及仅对内部状态进行操作的动画对象。下面我们定义一个类:
var Animation = function() { 
//动画类 
}; 
Animation.prototype.start = function() { 
//启用动画 
}; 
Animation.prototype.stop = function() { 
//停止动画 
}; 
/*用法如下*/ 
var anim = new Animation(); 
anim.start(); 
anim.stop();

如果你想将类的定义封装到一条声明中,则代码如下:
var Animation = function() { 
//动画类 
}; 
Animation.prototype = { 
start: function(){ 
//启用动画 
}, 
stop: function(){ 
//停止动画 
} 
};

这样让面向对象的程序员看起来更加眼熟,我们可以试着尝试更复杂一点的写法:
Function.prototype.method = function(name, fn){ 
this.prototype[name] = fn; 
} 
var Animation = function() { 
//动画类 
}; 
Animation.method("start", function(){ 
//启用动画 
}); 
Animation.method("stop", function(){ 
//停止动画 
});

我们为Function类扩展了一个方法method用于添加新方法。name代表函数名称,fn代表函数的具体实现。在基于此写法的基础之上,我们可以让函数支持链式调用:
Function.prototype.method = function(name, fn){ 
this.prototype[name] = fn; 
return this; 
} 
var Animation = function() { 
//动画类 
}; 
Animation.method("start", function(){ 
//启用动画 
}).method("stop", function(){ 
//停止动画 
});

至此已经见识了5种不同的编程风格,具有不同的代码量、编码效率和执行性能。你可以选择最适合当前项目的编程风格来进行工作。

2. Javascript是一门弱类型语言。声明变量时不必指定类型,但并不代表没有类型。Javascript包含三种基本类型:布尔型、数值型和字符串类型,此外还包含对象类型和函数类型,最后还包含空类型和未定义类型。基本类型按值传递,其他类型按引用传递。可以根据变量赋值改变类型,基本类型之间可以相互转换。toString()可以把数值或布尔值转化为字符串,parseInt()和parseFloat()可以将字符串转化为数值,双"非"操作可以将字符串或数值转化为布尔值。

3. Javascript函数是"一等"对象。函数可以存储在变量中,可作为参数传到其他函数,可作为返回值从其他函数中传出,也可在运行时构造。在于函数打交道时,带来了极大的灵活性和极强的表达能力,这些都是构建面向对象的基础。可以通过function() {...}创建匿名函数(没有函数名,也可赋给变量)。下面以例子来说明:

(function(){ 
var a = 10; 
var b = 5; 
alert(a * b);//返回50 
})();//函数定义就立即执行

之所以能立即执行,是因为函数声明后的一对括号。但我们发现,括号内空无一物,也并非完全如此。
(function(a, b){ 
alert(a * b);//返回50 
})(10, 5);//与前面等价

这个匿名函数与前一个等价,只是变量没有在函数内声明,而是直接从外部传入而已。其实,这个匿名函数也可以有个返回值,并赋给某个变量。
var c = (function(a, b){ 
return a * b;//返回50 
})(10, 5);//与前面等价 
alert(c);//50

匿名函数的最大用途是创建闭包。所谓闭包,就是一个受保护的变量空间,由内嵌函数生成。由于Javascript具有函数级的作用域,即定义在函数内部的变量在函数外部是不能被访问的,函数仅运行在定义它的作用域中,而不是在调用的作用域中。这样,就可以把变量包裹在匿名函数中加以保护。例如,你可以通过以下方式创建私有变量:
var c; 
(function(){ 
var a = 10; 
var b = 5; 
c = function(){ 
return a * b;//返回50 
} 
})(); 
c();//c可以访问a,b,即使它在匿名函数的外部也能被执行

4. Javascript对象是"易变"的。一切都是对象(除了3种基本类型),而且所有对象都是易变的。这意味着你能使用一些别的语言不存在的技术。例如为函数动态添加属性。
function displayError(error){ 
displayError.numTimesExecuted++; 
alert(error); 
} 
displayError.numTimesExecuted = 0;//意味着可对预先定义的类和对象进行修改

可以利用prototype机制在类的实例创建后再动态添加,此时对已定义的对象仍然有效。例如:
function Person(name, age) { 
this.name = name; 
this.age = age; 
} 
Person.prototype = { 
getName: function() { 
return this.name; 
}, 
getAge: function() { 
return this.age; 
} 
}; 
//先定义两个变量 
var miracle = new Person("Miracle", 28); 
var mike = new Person("Mike", 32); 
//动态添加一个方法 
Person.prototype.getGreeting = function() { 
return "Hello " + this.getName() + "!"; 
}; 
//displayGreeting()仅对Miracle有效 
miracle.displayGreeting = function() { 
alert(this.getGreeting()); 
}

与对象的易变性相关的就是反射(也可称为"内省"),即在运行时检查对象的属性和方法,并利用这些信息来实例化类和执行方法,甚至在开发时不需要知道它们的名称。借助于对象的这两大特性,可以完全模仿面向对象语言的高级特性,但要记住在Javascript中任何对象都是可以在运行时修改。

5. Javascript具有实现"继承"的天份。这里简单提及一下:Javascript继承包含"类式"继承和基于对象的原型式继承,这个话题我会在下一期的文章中详细论述。

最后总结一下,之所以采用面向对象和设计模式的思想来处理Javascript这种看似过程式的语言,到底有什么好处呢?我总结了以下几点供大家参考:

(1).可维护性。有助于降低模块之间的耦合性,对项目中代码可按模块和功能职责来划分。

(2).便于交流。对于一个大型团队来说,可能用设计模式很简单的术语可以高度概括你所负责实现的功能模块,而不必太多让团队其他成员关注过多的细节。

(3).提升性能。利用模式可以减少传送到客户端代码量的同时并提高程序运行的速度。

当然,有利就有弊。弊端在于:

(1).复杂度相对较高。获取可维护性的代价是以代码的高度重构和模块化的划分而成,对于一些新手来说,很难一下适应。

(2).部分模式反而降低性能。但是这种拖累依赖于你的项目需求,可能有时微不足道,有时难以接受。

因此,建议大家学会理解设计模式的应用场景,用对场景才是对设计模式的真正意义上的应用。盲目应用和用错场景就是误用,还不如不用。

Javascript 相关文章推荐
070823更新的一个[消息提示框]组件 兼容ie7
Aug 29 Javascript
url地址自动加#号问题说明
Aug 21 Javascript
实现只能输入数字的input不用replace方法
Sep 12 Javascript
jquery form 加载数据示例
Apr 21 Javascript
星期几的不同脚本写法(推荐)
Jun 01 Javascript
JavaScript中Number对象的toFixed() 方法详解
Sep 02 Javascript
jQuery实现导航高亮的方法【附demo源码下载】
Nov 09 Javascript
Bootstrap table使用方法详细介绍
Dec 09 Javascript
React中ES5与ES6写法的区别总结
Apr 21 Javascript
动态创建Angular组件实现popup弹窗功能
Sep 15 Javascript
JavaScript Math对象和调试程序的方法分析
May 13 Javascript
vue vantUI tab切换时 list组件不触发load事件的问题及解决方法
Feb 14 Javascript
MooBox 基于Mootools的对话框插件
Jan 20 #Javascript
formStorage 基于jquery的一个插件(存储表单中元素的状态到本地)
Jan 20 #Javascript
json的前台操作和后台操作实现代码
Jan 20 #Javascript
Prototype源码浅析 Enumerable部分(二)
Jan 18 #Javascript
JS中的public和private对象,即static修饰符
Jan 18 #Javascript
DOM 中的事件处理介绍
Jan 18 #Javascript
深入理解JavaScript系列(13) This? Yes,this!
Jan 18 #Javascript
You might like
实现树状结构的两种方法
2006/10/09 PHP
我的论坛源代码(九)
2006/10/09 PHP
PHP+MySQL 手工注入语句大全 推荐
2009/10/30 PHP
修复ShopNC使用QQ 互联时提示100010 错误
2015/11/08 PHP
PHP自带方法验证邮箱、URL、IP是否合法的函数
2016/12/08 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
2017/07/21 PHP
php实现的简单多进程服务器类完整示例
2020/02/01 PHP
javascript实现unicode和字符的互相转换
2007/07/18 Javascript
javascript获取web应用根目录的方法
2014/02/12 Javascript
js获取当前地址 JS获取当前URL的示例代码
2014/02/26 Javascript
Node.js中的流(Stream)介绍
2015/03/30 Javascript
js实现二级菜单渐隐显示
2015/11/03 Javascript
轻松学习jQuery插件EasyUI EasyUI表单验证
2015/12/01 Javascript
使用jQuery制作遮罩层弹出效果的极简实例分享
2016/05/12 Javascript
浅谈javascript中的 “ && ” 和 “ || ”
2017/02/02 Javascript
巧用weui.topTips验证数据的实例
2017/04/17 Javascript
jQuery.form.js的使用详解
2017/06/14 jQuery
vue轮播图插件vue-concise-slider的使用
2018/03/13 Javascript
聊聊Vue 中 title 的动态修改问题
2019/06/11 Javascript
js编写简易的计算器
2020/07/29 Javascript
Python中的with...as用法介绍
2015/05/28 Python
python实现机械分词之逆向最大匹配算法代码示例
2017/12/13 Python
python调用Matplotlib绘制分布点并且添加标签
2018/05/31 Python
Python检查和同步本地时间(北京时间)的实现方法
2018/12/03 Python
Python和Go语言的区别总结
2019/02/20 Python
使用OpenCV实现仿射变换—平移功能
2019/08/29 Python
Django 用户认证Auth组件的使用
2020/11/30 Python
仓库管理专业个人自我评价范文
2013/11/11 职场文书
优秀员工表扬信
2014/01/17 职场文书
产品发布会策划方案
2014/05/12 职场文书
群众路线对照检查材料
2014/09/22 职场文书
老干部工作汇报材料
2014/10/28 职场文书
Mysql中调试存储过程最简单的方法
2021/06/30 MySQL
python库sklearn常用操作
2021/08/23 Python
一些让Python代码简洁的实用技巧总结
2021/08/23 Python
Django框架模板用法详解
2022/06/10 Python