- 浏览: 1164663 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (224)
- Web UI (11)
- Dynamic Language (7)
- Framework (9)
- Note & Try (17)
- JavaScript (38)
- Ant/Gant/Maven (2)
- Database (5)
- Software Engineering (13)
- Career (29)
- Team Management (5)
- Performance (12)
- Algorithm (17)
- News & Commets (23)
- System Design (17)
- OO Design (8)
- API Design (3)
- Programming Paradigms (8)
- Asynchronous Programming (5)
- Architecture (6)
最新评论
-
a2320064997:
请问博主,排序的动图是怎么做出来的?
排序算法一览(二):归并类排序、分布类排序和混合类排序 -
你的微笑我得阳光:
试试验证码
reCAPTCHA项目 -
mack:
一般采用json
对象转换的问题 -
fly_hyp:
我也做了一个中文编程软件,叫趣智思成
一些中文编程语言 -
facingSun:
受教了
前端解耦的一个最简单示例
var Player = (function(){ Player = function(){ //这只是个空壳 throw new Error("Can not instantiate a Player object."); }; Player.MIN_EXTENDED_TIME = 1; Player.MAX_EXTENDED_TIME = 3; Player._player = false; Player.getInstance = function(){ if(!Player._player){ alert("Init..."); Player._player = { _name : name, setName : function(name){ this._name = name; }, toString : function(){ return "Player: " + this._name; } }; } return Player._player; }; return Player; //把修缮完工的Player这个组件方法返回 })(); //var player = new Player(); //new Player()会抛出异常 var player1 = Player.getInstance(); var player2 = Player.getInstance(); player2.setName("RealPlayer"); alert(player2.toString()); //输出RealPlayer
终于要定义一个组件方法了,利用原型来实现。看看这样如何:
function Player(name){ Player.MIN_EXTENDED_TIME = 1; Player.MAX_EXTENDED_TIME = 3; this._name = name; }; Player.prototype.setName = function(name){ this._name = name; }; Player.prototype.toString = function(){ return "Player: " + this._name; }; var player = new Player("WindowsMediaPlayer"); alert(player.toString()); //输出WindowsMediaPlayer player.setName("RealPlayer"); alert(player.toString()); //输出RealPlayer alert(Player.MAX_EXTENDED_TIME);
恩,有封装、有常量、也有复写了Object的toString方法,至于继承之类的事情,咱们后面再说,初看看还不错。可是这样的组件方法定义不够优雅,也不够直观,方法都是放在独立的位置定义的,并没有和最开始的组件方法放置在一起,如果能像Java那样定义岂不更好?
对了,可以用闭包来实现。试试看吧:
function Player(name){ Player.MIN_EXTENDED_TIME = 1; Player.MAX_EXTENDED_TIME = 3; this._name = name; this.setName = function(name){ this._name = name; }; this.toString = function(){ return "Player: " + this._name; }; }; var player = new Player("WindowsMediaPlayer"); alert(player.toString()); //输出WindowsMediaPlayer player.setName("RealPlayer"); alert(player.toString()); //输出RealPlayer alert(Player.MAX_EXTENDED_TIME);
不像Groovy里面,闭包做了很大程度上的强化,包括新的语法的支持;JavaScript的闭包是很简单的闭包,它没有特殊的需要额外学习的语法,任意一个function,里面只要包含未绑定变量,这些变量是在function所属的上下文环境中定义的,那么,这个function就是闭包。顺便罗嗦一句,和闭包相反的,不正是不包含任何未绑定变量的函数式代码吗?
写是写好了,可是转念一想,Player应当只有一份,它是单例的,最好我也能像Java那样弄一个单例模式出来 :),可是事不遂愿,我没有办法在JavaScript做一个private的构造器,用这种思路去实现单例模式似乎不可行……
怎么办?
然而天无绝人之路,我控制不了你new一个Player的对象,我却可以控制你new出来的这个Player对象的属性和行为!当你需要使用你new出来的Player的对象的时候,你发现根本无法完成,或者它只是一个空壳!真正的东西还是要靠单例中经典的getInstance方法来获得:
function Player(){ throw new Error("Can not instantiate a Player object."); }; //这只是个空壳 (function(){ //这才是货真价实的东西 Player.MIN_EXTENDED_TIME = 1; Player.MAX_EXTENDED_TIME = 3; Player._player = false; Player.getInstance = function(){ if(!Player._player){ alert("Init..."); Player._player = { _name : name, setName : function(name){ this._name = name; }, toString : function(name){ return "Player: " + this._name; } }; } return Player._player; }; })(); //var player = new Player(); //new Player()会抛出异常 var player1 = Player.getInstance(); var player2 = Player.getInstance(); player2.setName("RealPlayer"); alert(player2.toString()); //输出RealPlayer
好,真不错,单例模式在JavaScript下也成功实施了——你要胆敢new Player();就会抛出一个异常,这样什么也得不到,只有用getInstance方法得到的对象才是真真正正的Player对象。上面的代码整个执行的结果,只弹出了一次"Init..."的对话框,说明真正的“构造器逻辑”只调用了一次。
都做到这份上了,依然有小小的遗憾,Player的定义依然被拆分成了两部分,一部分定义空壳,一部分是一个匿名函数来定义Player的常量和getInstance方法。这两部分就不能合二为一么?
能。只需要用到一个小小的匿名函数,如果耐心从头看到这里,也一定能理解:
var Player = (function(){ Player = function(){ //这只是个空壳 throw new Error("Can not instantiate a Player object."); }; Player.MIN_EXTENDED_TIME = 1; Player.MAX_EXTENDED_TIME = 3; Player._player = false; Player.getInstance = function(){ if(!Player._player){ alert("Init..."); Player._player = { _name : name, setName : function(name){ this._name = name; }, toString : function(name){ return "Player: " + this._name; } }; } return Player._player; }; return Player; //把修缮完工的Player这个组件方法返回 })(); //var player = new Player(); //new Player()会抛出异常 var player1 = Player.getInstance(); var player2 = Player.getInstance(); player2.setName("RealPlayer"); alert(player2.toString()); //输出RealPlayer
到此,终于如释重负,深入理解JavaScript面向对象,用好原型和闭包这两把锋利的武器,才能写出优秀的前端代码来。有一些同事私下和我交流,后面我尽量贴简洁的代码,希望有面向对象基础和JavaScript基础的同事都能有所收获。
文章系本人原创,转载请注明作者和出处
评论
return "Player: " + this._name;
}
这个方法是不应该有参数的吧。
已修正。
return "Player: " + this._name;
}
这个方法是不应该有参数的吧。
发表评论
-
JavaScript 3D图表
2013-08-24 19:36 3135在说3D图表以前,首先要明确两个概念,一个是数据的维度,一个 ... -
几道容易出错的JavaScript题目
2013-07-07 10:34 2277下面这几道JavaScript题目大多来自于周五的一个小分享 ... -
JavaScript使用for循环时出现的问题
2013-05-26 00:36 1667这个问题的讨论最初来自公司内部邮件,我只是把这个问题的讨论内 ... -
DNS劫持
2013-04-30 13:59 2183想谈一谈这个话题是因为最近有一位朋友抱怨他的博客在某些用户某 ... -
你没有抓住Promises的要点
2013-04-21 20:52 2477注:这篇文章翻译自《You're Missing the P ... -
程序员,都去写一写前端代码吧
2013-01-19 01:16 2685你可以认为我是一个极 ... -
用JavaScript截图
2013-01-08 23:13 7666使用JavaScript截图,这里我要推荐两款开源组件: ... -
JQuery表格插件介绍:Flexigrid和DataTables
2012-12-27 11:35 8990JQuery的表格插件有很多。Flexigrid和Dat ... -
Flot介绍
2012-12-22 18:56 2375最近在项目里面要用到JavaScript来绘制图表,JQ ... -
Function Invocation Patterns
2012-11-04 17:46 1379今天看到微博上大家在讨论一个JavaScript的小问题 ... -
d3介绍
2012-10-31 00:17 2614D3.js是一个基于数据的操作文档的JavaScript ... -
Dart,你凭什么挑战JavaScript?
2012-09-26 08:46 5856不妨先来打量一下JavaScript。JavaScrip ... -
Backbone.js介绍
2012-05-08 22:57 4479注:教程请参见这里(本文有很多内容都是从这里翻译的),官方网站 ... -
关于CommonJS
2012-03-26 00:37 17295老实说,之前我对CommonJS也是一无所知,直到不久前Nod ... -
同步、异步转化和任务执行
2012-01-24 22:23 4244正如动静是相对的概念,有了它们,世界才充满盎然生气;变和不变也 ... -
JavaScript实现继承的几种方式
2012-01-07 23:21 12413在这篇文章中,介绍了 ... -
JavaScript重构(十):强化对象封装和模块封装
2011-09-19 22:44 36861、类本身就是一种封装形式,先来看看最简单的封装,JavaSc ... -
JavaScript 的 delete 用法
2011-01-09 11:59 17401、 var o = {}; o.x = new Ob ... -
疯狂的跨域技术
2011-01-09 19:39 2529[转]疯狂的跨域技术 原帖地址:http://itgeeker ... -
服务器端JavaScript
2011-01-11 00:05 1351JSConf2010的重要议题之一:node.js。 不要觉 ...
相关推荐
- **基础概念**:介绍了JavaScript如何实现面向对象编程的基本原理,包括构造函数、原型链、继承机制等。 - **实战应用**:讲解如何利用这些概念来构建可扩展和易于维护的代码。 - **函数式JavaScript**: - **...
- **闭包**:利用闭包可以创建私有变量和方法,避免全局污染。 - **原型链**:通过原型链实现对象间的继承,一个对象可以继承另一个对象的属性和方法。 - **动态性**:JavaScript的动态类型特性使得在运行时可以改变...
2. **高级特性**:闭包、原型链、作用域、this关键字、函数表达式、箭头函数、模块化(CommonJS、ES6模块)、Promise、异步编程等。 3. **DOM操作**:通过JavaScript与HTML文档对象模型进行交互,包括元素选择、...
通过阅读和分析这些源代码,你可以深入理解JavaScript的基本语法、数据类型、控制结构、函数、对象、闭包、原型链等核心概念。同时,源代码还可能涵盖了DOM操作、事件处理、AJAX异步通信、ES6及以上的语法特性,如...
### JavaScript编程精解知识点概述 #### 一、JavaScript简介 **JavaScript**是一种广泛...通过以上知识点的学习和实践,开发者可以更加深入地理解 JavaScript,并能够利用这些知识解决实际问题,提高开发效率和质量。
4. **原型和原型链**:JavaScript的继承机制基于原型,通过原型对象实现属性和方法的共享。原型链是查找对象属性的路径,理解这一机制有助于掌握对象间的关联。 5. **事件和事件处理**:JavaScript与DOM交互的一个...
JavaScript,简称JS,是一种轻量...每个实例都是一次实践的机会,通过阅读、理解和重构代码,你可以不断提升自己的编程技能,成为JavaScript的专家。同时,这些实例也可以作为开发过程中的参考资料,快速解决实际问题。
书中详细讨论了函数和对象的优化策略,包括函数表达式、立即执行函数、对象属性访问和优化、以及如何利用原型链来提高代码复用。此外,还特别关注了异步编程,如回调函数、Promise和async/await,这些都是现代...
- 代码优化:学习编写高效、可维护的JavaScript代码,包括避免全局变量、使用let和const、代码重构等。 - 错误处理:掌握如何有效地捕获和处理运行时错误,以及使用try...catch语句。 - 调试技巧:使用浏览器...
在JavaScript中,我们可以使用函数和闭包来实现封装,通过`this`关键字来引用对象的属性和方法。例如: ```javascript function Person(name) { this.name = name; this.sayHello = function() { console.log(`...
- **对象与原型**:第一章“Objects and Prototyping”深入探讨了JavaScript中的对象和原型机制。这部分内容对于理解JavaScript的核心概念至关重要。通过学习这一章,读者可以掌握如何创建自定义对象,理解对象之间...
这段代码中,`Class`既是一个闭包,又是一个构造函数,同时还定义了一些私有变量和方法。 #### 七、处理Ajax返回的JS脚本 `Function`还可以用来处理Ajax请求返回的JavaScript脚本: ```javascript var ajax_js_...
5. **对象和原型**:理解JavaScript中的对象和原型链,学习如何创建和操作对象,以及原型继承。 6. **函数式编程**:可能包含一些函数式编程的概念,如高阶函数、柯里化、纯函数等。 7. **异步编程**:了解回调...
这个部分重点介绍了原型和原型链的概念,这是理解JavaScript继承和对象创建机制的关键;闭包和作用域的理解,有助于编写更优雅的代码;"this"关键字的深入分析,将帮助开发者解决函数执行上下文的问题;模块化章节让...
《JavaScript超强版》可能是对JavaScript全面深入的解析,包括语言基础、数据类型、控制结构、函数、对象、原型链、闭包等核心概念,以及DOM操作、AJAX异步通信、BOM浏览器对象模型等相关知识。这本书可能还会涉及...