JavaScript设计模式与开发实践 面向对象
Posted Surahe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript设计模式与开发实践 面向对象相关的知识,希望对你有一定的参考价值。
1 动态类型语言
静态类型语言编译时就已经确定变量类型,动态类型语言的变量类型要到程序运行时,变量被赋予某个值后,才会有类型。
静态语言的优点:首先,编译时就能发现类型不匹配错误,其次如果程序明确规定数据类型,编译器还能针对这些信息对程序进行优化,提高程序执行速度。
静态语言的缺点:迫使程序员按照强契约编写程序,并且增加更多代码。
动态语言的优点:编写的代码更少,程序员能把精力放到业务逻辑。
动态语言的缺点:无法保证变量的类型,再程序运行时可能发现类型相关错误。
动态类型无需进行类型检测,我们可以尝试钓鱼任何对象的任意方法,不用考虑它原本是否被设计为拥有该方法。
2 多态
多态的实际含义:同意操作作用于不同的对象上,可以产生不同的解释和不同的结果。也就是,给不同的对象发送同一个消息,这些对象会根据这个消息分别给出不同反馈。
var makeSound = function( animal ){ if ( animal instanceof Duck ){ console.log( ‘嘎嘎嘎‘ ); }else if ( animal instanceof Chicken ){ console.log( ‘咯咯咯‘ ); } }; var Duck = function(){}; var Chicken = function(){}; makeSound( new Duck() ); // 嘎嘎嘎 makeSound( new Chicken() ); // 咯咯咯
这段代码体现了多态性,但再增加一个动物后需要改动makeSound函数。
多态的思想是将不变的事物和可变的事物分开。把不变的部分隔离,把可变的封装,,这给予我们扩展程序的能力。
//把不变的部分隔离,即动物都会发出叫声 var makeSound = function( animal ){ animal.sound(); }; //把可变的部分各自封装,多态实际上是对象的多态 var Duck = function(){}; Duck.prototype.sound = function(){ console.log( ‘嘎嘎嘎‘ ); }; var Chicken = function(){}; Chicken.prototype.sound = function(){ console.log( ‘咯咯咯‘ ); }; makeSound( new Duck() ); // 嘎嘎嘎 makeSound( new Chicken() ); // 咯咯咯 var Dog = function(){}; Dog.prototype.sound = function(){ console.log( ‘汪汪汪‘ ); }; makeSound( new Dog() ); // 汪汪汪
多态最根本的作用是通过把过程化的条件分局转化为对象的多态性,从而消除条件分句。将行为分布在各个对象中,并让对象各自负责自己的行为,正是面向对象设计的优点。
var googleMap = { show: function(){ console.log( ‘开始渲染谷歌地图‘ ); } }; var baiduMap = { show: function(){ console.log( ‘开始渲染百度地图‘ ); } };
// 使用条件分句 var renderMap = function( type ){ if ( type === ‘google‘ ){ googleMap.show(); }else if ( type === ‘baidu‘ ){ baiduMap.show(); } }; renderMap( ‘google‘ ); // 输出:开始渲染谷歌地图 renderMap( ‘baidu‘ ); // 输出:开始渲染百度地图
//使用多态 var renderMap = function( map ){ if ( map.show instanceof Function ){ map.show(); } }; renderMap( googleMap ); // 输出:开始渲染谷歌地图 renderMap( baiduMap ); // 输出:开始渲染百度地图
3 封装
封装的目的是将信息隐藏。封装包括封装数据、封装实现、封装类型和封装变化。封装不仅仅是隐藏数据,还包括隐藏实现细节、设计细节以及隐藏对象的类型等。
封装数据:javascript没有public、private、protected等,只能用变量作用域实现封装特性,只能模拟public和private。
封装实现:封装使得对象之间的耦合松散,对象之间只通过暴露的API接口通信。修改一个对象时,只要对外的接口没有变化,就不会影响程序的其他功能。
封装类型:JavaScript没有对抽象类和接口的支持.
封装变化:《设计模式》总结了23种设计模式,分别被划分为创建新模式、结构型模式和行为型模式。创建型模式,要创建一个对象是一种抽象行为,具体创建什么对象是可以变化的,
创建型模式的目的是封装对象的变化。结构型模式封装的是对象直接的组合关系。行为型模式封装的是对象的行为变化。
4 原型模式和基于原型继承的JavaScript对象系统
原型编程范型的部分基本规则:
- 所有的数据都是对象
- 要得到一个对象,不少通过实例化类,而是找到一个对象作为原型并克隆它
- 对象会记住它的原型
- 如果对象无法响应某个请求,会把这个请求委托给它的原型
1 所有的数据都是对象
JavaScript的基本类型包括undefined、number、string、boolean、object、function。除了undefined,number、boolean、string都可以通过包装类编程对象类型,JavaScript的根对象是Object.prorotype。
2 要得到一个对象,不少通过实例化类,而是找到一个对象作为原型并克 function Person( name ){
this.name = name; }; Person.prototype.getName = function(){ return this.name; }; var a = new Person( ‘sven‘ ) console.log( a.name ); // 输出:sven console.log( a.getName() ); // 输出:sven
//ES5中的Object.getPrototypeOf可以看对象 console.log( Object.getPrototypeOf( a ) === Person.prototype ); // 输出:true
当使用new调用函数,函数就是一个构造器,先克隆Object.prototype对象,再进行其他操作。
在Chrome和Firefox等暴露了对象__proto__属性的浏览器理解new运算的过程
var objectFactory = function(){ var obj = new Object(), // 从Object.prototype 上克隆一个空的对象 Constructor = [].shift.call( arguments ); // 取得外部传入的构造器,此例是Person obj.__proto__ = Constructor.prototype; // 指向正确的原型 var ret = Constructor.apply( obj, arguments ); // 借用外部传入的构造器给obj 设置属性 return typeof ret === ‘object‘ ? ret : obj; // 确保构造器总是会返回一个对象 };
3 对象会记住它的原型
某个对象的_proto_属性默认会指向它的构造器的原型对象,即Constructor.prototype。正是因为对象要通过__prototype__属性记住它的构造器的原型,模拟new创建对象时需要手动给obj对象设置正确的__proto__指向。
以上是关于JavaScript设计模式与开发实践 面向对象的主要内容,如果未能解决你的问题,请参考以下文章