javascript面向对象实现java常用的1StringBuffer,Map,Collection,List,Set

本文主要是介绍javascript面向对象实现java常用的1StringBuffer,Map,Collection,List,Set,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

javascript面向对象实现java常用的StringBuffer,Map,Collection,List,Set

1前言

       在开发中,我们做java后台开发的,普遍都是擅长后端语言,对于javascript却不甚理想。偶尔我们会去w3c看看javascript的基本语法,但是每次都是学习不到位,用起来感觉总是马马马虎虎。在最近的开发中,这个老大难的问题又出现在了我面前。一开始,继续忽略,一张手就是定义了一个function xxx(){}。但是噩梦往往都是因为懒惰造成的,由于开发的需要,某个页面的js文件多大1000 line+,方法至少也是10+了。作为一个开发人员,目睹着自己的代码,尽然会超出自己的控制,显然让人不甘心啊,于是乎,重构了很多代码,但是依旧木有使用到面向对象的编程范式。在折腾了几天后,终于下定决心,使用面向对象的技术来重写整个js文件的代码。

要想用好面向对象,那么就需要理解面向对象的编程思想,作为一个后台开发人员,就不多说了,面向对象最主要的四个特性:继承,多态,封装,抽象。更加详细的内容,请参考面向对象的相关数据。

java中,我们使用class来定义一个类,用于规范某种对象的特性(属性,方法),当该class定义好之后,就可以使用new ClassXxx()的方式来实例化一个对象,并且所有同一个class生成的对象都具备着一致的特性(属性,方法),后期不能动态的给对象添加属性与方法。对于这种后期模式的开发语言来说,优势非常明显,那就是所有对象的属性与方法都确定了下来,并且可以通过预编译,将class转换成二进制的机器码,所以在运行效率上会比较有优势。但是缺点也同样非常明显,比如需要编译源码,不能动态添加属性或者方法,开发效率较低等。


2面向对象技术

  在javascript中,有如下几种数据类型,分别是:undefined,boolean,string,number,object,function。这里面,我们只关注object(对象)。对象是javascript的基本数据类型,将很多值聚合在一起,可以通过名字访问这些值。比如:{name:骆宏, age:20}。每一个对象除了保持自有的属性,通常还可以从一个称为原型的对象那里继承属性,通常情况下,会继承原型的方法。Javascript对象是动态的,可以动态的添加属性,或者删除属性,与java这类语言类型不一样。


2.1javascript的继承

      在java中,所有的对象都继承java.lang.Object,并且是单根继承。在javascript中也类型,所有的对象原型都继承Object.prototype对象。在这里面,我们需要特别注意的是:每个对象都引用着一个原型对象,比如Student对象引用着一个Student.prototype,并且这个Student.prototype同时也引用着Object.prototype,我们称之为javascript的原型链。下面我们假设有如下的继承关系:


  在这里面,正方形对象继承了矩形,矩形继承了多边形,多边形继承了形状,而形状继承了Object。于是正方形对象就可以获得从Object.prototype+形状.prototype+多边形.prototype+矩形.prototype的所有属性(除了一些不可以继承的属性)。一个对象在寻找属性时,会首先查找自身是否有这个属性,如果找不到,就会去到该对象的原型中选中,如果也找不到,就会递归的往Object.prototype方向去寻找该属性。我们称之为该对象的继承关系的原型链(非严肃的说法,官方定义请查阅w3c的javascript规范)。


2.2javascript对象的实例化

1工厂方式
function createCar() {var oTempCar = new Object;  //实例化一个对象oTempCar.color = "blue";  //给对象赋值oTempCar.doors = 4;oTempCar.mpg = 25;oTempCar.showColor = function() {  //属性的值可以为方法alert(this.color);};return oTempCar;  //返回对象
}
使用方式:var car = createCar();

2构造函数方式
function Car(sColor,iDoors,iMpg) {this.color = sColor;  //使用this来表示当前的对象this.doors = iDoors;this.mpg = iMpg;this.showColor = function() {  //每次创建对象时,都需要创建一个匿名函数alert(this.color);};
}
使用方式:var car = new Car(“红色”, “是”, “是”);

3原型方式

  在方式中2,每次创建一个Car时,都是实例化this.showColor,但是通过观察,我们可以发现,这其实是一个方法,只需要实例化一次即可。为了改进上述代码,使用原型的方式重写上诉的代码,如下:

function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");
}Car.prototype.showColor = function() {  //将该方法放在原型的属性上,所有的Car                       //对象都从这个原型对象继承该属性alert(this.color);
};

4动态原型方式

function Car(sColor,iDoors,iMpg) {this.color = sColor;this.doors = iDoors;this.mpg = iMpg;this.drivers = new Array("Mike","John");if (typeof Car._initialized == "undefined") {  //给构造方法添加一个属性,记录下第//一次实例化Car.prototype.showColor = function() {alert(this.color);};Car._initialized = true;   //标志着该对象已经实例化过了}
}

5混合工厂模式

function Car() {var oTempCar = new Object;oTempCar.color = "blue";oTempCar.doors = 4;oTempCar.mpg = 25;oTempCar.showColor = function() {alert(this.color);};return oTempCar;
 

  在实际开发中,那么我们该使用哪种方式呢?在目前,原型方式与动态原型方式都比较流行,个人推荐动态原型的方式,因为可以将所有代码集中在构造函数内部,避免代码分散在多个地方。


2.3使用javascript技术模拟java中常用的类

StringBuffer

function StringBuffer(){this.strs = [];  //用数组来缓存所有的内容if(typeof StringBuffer._initialized == "undefined"){StringBuffer._initalized = true;  //已经初始化过了,不需要重复初始化StringBuffer.prototype.append = function(str){this.strs.push(str);return this;};//覆写toString,避免使用Object.toStringStringBuffer.prototype.toString = function(seperator){if(!seperator){seperator = "";}return this.strs.join(seperator);};}
}


Map

function Map(){this.elements = new Array();  if(typeof Map._initialized == "undefined"){Map._initialized = true;  //记录下已经实例化的标识符Map.prototype.size = function(){return this.elements.length;};Map.prototype.isEmpty = function(){return this.elements.length == 0;};Map.prototype.clear = function(){this.elements = new Array();};Map.prototype.put = function(key, value){if(key == null || value == null) throw TypeError(); var exists = false;if(this.isEmpty()){this.elements.push({"key": key, "value": value});}else{  for(var i=0; i<this.elements.length; i++){if(this.elements[i].key == key){  //overridethis.elements[i].value = value;exists = true;}}if(!exists){this.elements.push({"key": key, "value": value});}}};Map.prototype.get = function(key){if(key == null) throw TypeError();if(this.isEmpty()) return null;for(var i=0; i<this.elements.length; i++){if(this.elements[i].key == key) return this.elements[i].value;}return null;};Map.prototype.remove = function(key){if(key == null) throw TypeError();if(this.isEmpty()) return false;for(var i = 0; i < this.elements.length; i++) {     if(this.elements[i].key == key) {     this.elements.splice(i, 1);     //delete elements[i] return true;     }     }  return false;};Map.prototype.containsKey = function(key){if(key == null) throw TypeError();if(this.isEmpty()) return false;for(var i = 0; i < this.elements.length; i++) {     if(this.elements[i].key == key) {     return true;     }     }  return false;};Map.prototype.containsValue = function(value){if(value == null) throw TypeError();if(this.isEmpty()) return false;for(var i = 0; i < this.elements.length; i++) {     if(this.elements[i].value == value) {     return true;     }     }  return false;};Map.prototype.keys = function(){if(this.isEmpty()) return [];var keys = new Array();for(var i=0; i<this.elements.length; i++){keys.push(this.elements[i].key);}return keys;};Map.prototype.values = function(){if(this.isEmpty()) return [];var values = new Array();for(var i=0; i<this.elements.length; i++){values.push(this.elements[i].value);}return values;};Map.prototype.toString = function(){if(this.isEmpty()) return "[{}]";var sb = new StringBuffer();sb.append("[");for(var i=0; i<this.elements.length; i++){sb.append("{").append(this.elements[i].key).append(",").append(this.elements[i].value).append("}");if(i != this.elements.length - 1){sb.append(",");}}sb.append("]");return sb.toString();};}
}

Collection

function Collection(){this.elements = new Array();
}Collection.prototype.add = function(obj){if(obj == null) throw TypeError();this.elements.push(obj);return true;
};Collection.prototype.addAll = function(objs){if(objs == null) throw TypeError();this.elements = this.elements.concat(objs);return true;
};Collection.prototype.get = function(index){this._checkIndex(index);if(this.isEmpty()) return null;return this.elements[index];
};/*** 删除下表为index的元素* */
Collection.prototype.removeIndex = function(index){this._checkIndex(index);this.elements.splice(index, 1);     //delete elements[i-1]
};/*** 删除某个元素* 这里面会从下表0开始便利,删除第一个匹配的元素* */
Collection.prototype.removeObj = function(obj){if(this.isEmpty()) return false;for(var i=0; i<this.elements.length; i++){if(this.elements[i] == obj){this.elements.splice(i-1, 1);     //delete elements[i]}}
};Collection.prototype.contains = function(obj){if(obj == null) throw TypeError();if(this.isEmpty()) return false;for(var i=0; i<this.elements.length; i++){if(this.elements[i] == obj){return true;}}return false;
};Collection.prototype.containsAll = function(objs){if(objs == null) throw TypeError();if(objs.length > this.elements.length) return false;for(var i=0; i<objs.length; i++){if(this.contains(objs[i]) == false){return false;}}return true;
};Collection.prototype.size = function(){return this.elements.length;
};Collection.prototype.isEmpty = function(){return this.elements.length == 0;
};Collection.prototype.clear = function(){this.elements = new Array();
};Collection.prototype._checkIndex = function(index){if(index < 0 || index >= this.elements.length){throw new Error("index must be in [0, " + this.elements.length + ")");}
};/*** 默认输入的格式如下:* [element1,element2,element3,...,elementx]* * 如果客户端需要获取类型数组join的效果,直接传入分隔符即可* 比如collection的内容为:a,b,c,默认的toString为[a,b,c],如果想要获得:abc,传入"";想要获得a,b,c,传入",",想要获得a b c,传入" "* * */
Collection.prototype.toString = function(separator){if(this.isEmpty()) return "";if(separator != null){return this.elements.join(separator);}else{var sb = new StringBuffer();sb.append("[");for(var i=0; i<this.elements.length; i++){sb.append(this.elements[i]);if(i != this.elements.length - 1){sb.append(",");}}sb.append("]");return sb.toString();}
};

List

/*** Collection的子类* 提供了如下几个增强方法:* set(index, obj)* subList* */
function List(){this.elements = new Array();  //这个属性不能使用Collection中的elements,因为原型对象都是collection,那样子会出现bug
}//List.prototype修改为new Collection对象,等价于继承了Collection的所有//属性
List.prototype = new Collection(); /*** 在第几个位置插入元素* */
List.prototype.set = function(index, obj){this._checkIndex(index);this.elements.splice(index, 0, obj);     //add elements[i]return true;
};/*** 获取子链表* */
List.prototype.subList = function(start, end){this._checkIndex(start);this._checkIndex(end);if(start >= end){throw new Error("start must be less than end.");}var subList = new Array();var index = 0;for(var i=start; i<end; i++){subList[index++] = this.elements[start];}return subList;
};

Set

/*** Collection子类* 因为Set中,元素不能重复,所以这里面override了Collection的add,addAll方法* */
function Set(){this.elements = new Array();  //这个属性不能使用Collection中的elements,因为原型对象都是collection,那样子会出现bug
}
Set.prototype = new Collection();  //继承Collection/*** 因为Set不允许重复元素存在,所以这里面需要override add,addAll方法* */
Set.prototype.add = function(obj){if(this.contains(obj)){return false;}else{this.elements.push(obj);return true;}
};Set.prototype.addAll = function(objs){if(objs == null) throw new TypeError("objs can't be null");for(var i=0; i<objs.length; i++){if(this.contains(objs[i])){continue;}else{this.elements.push(objs[i]);}}
};/*** 在第几个位置插入元素* */
Set.prototype.set = function(index, obj){this._checkIndex(index);if(this.contains(obj)){return false;}else{this.elements.splice(index, 0, obj);     //add elements[i]return true;				}
};


3总结

     每一个后端开发人员,都应该详细的解读下javascript,而不是大概知道怎样。在实战中,可以提高开发人员的开发效率,代码的可维护性也变得不再那么狼狈不堪。下次再写javascript代码时,当你一顺手写下function xxx(){}时,请再思考下吧。


关于面向对象技术,大家可以参考: 

1 Jquery源码分析

http://www.cnblogs.com/aaronjs/p/3279314.html

 

2 w3c面向对象技术

http://www.w3school.com.cn/js/pro_js_object_oriented.asp

 

3.IBM关于javascript面向对象的讲解

http://www.ibm.com/developerworks/cn/web/1304_zengyz_jsoo/








这篇关于javascript面向对象实现java常用的1StringBuffer,Map,Collection,List,Set的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992137

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上,或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景: 表单处理:通过 @ModelAttribute 将表单数据绑定到模型对象上预处理逻辑:在请求处理之前

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus