Js实现map和深拷贝map

深拷贝和浅拷贝的区别

1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用
2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”

为什么要使用深拷贝?
我们希望在改变新的数组(对象)的时候,不改变原数组(对象)

深拷贝的要求程度
我们在使用深拷贝的时候,一定要弄清楚我们对深拷贝的要求程度:是仅“深”拷贝第一层级的对象属性或数组元素,还是递归拷贝所有层级的对象属性和数组元素?

怎么检验深拷贝成功
改变任意一个新对象/数组中的属性/元素, 都不改变原对象/数组

var map = new Map();
map.putMap();  //实现深拷贝
/**
 * 类似java中的hashmap的类,key必须为字符串,如果是数字,key中的 1和"1"被认为是相等的
  引用该类的时候,不能同时引用自定义创建的Object原形方法。这样会导致for(var key in object)
  这样遍历的时候将会把自定义的Object的原型方法加入。
  * @class
*/
function Map(content, sep, equal) {
	this.elements = {};
	this.len = 0;
	this.separator = sep ? sep : ";";
	this.equal = equal ? equal : "=";
	this.merge(content);
}

Map.prototype = new Object;

Map.prototype.merge = function(str) {
	var s = str;
	// 如果s为undefine会到只js异常,所以改成!s
	if (!s || s.length == 0) {
		return;
	}

	var sep = this.separator;
	if (sep == "\r\n") {
		sep = "\n";
	}
	else if (sep == null || sep.length == 0) {
		sep = ";";
	}
	var equal = this.equal;
	var i1 = 0;
	var i2 = s.indexOf(equal, i1);
	while (i2 != -1) {
		while (i1 < i2 && (s.charAt(i1) == sep || s.charAt(i1) == '\r'))
			i1++;// 支持:a=1\r\n\r\nb=2\r\n
		var key = s.substring(i1, i2);
		var value;
		i1 = i2 + equal.length;
		if (i1 < s.length && s.charAt(i1) == '"') {
			var func = new extractQuotedStr(s, "\"", i1);
			value = func.getValue();
			i1 = func.getEndIndex() + sep.length;
		}
		else {
			i2 = s.indexOf(sep, i1);
			if (i2 == -1) {
				i2 = s.length;
			}
			value = s.substring(i1, sep == '\n' && s.charAt(i2 - 1) == '\r' ? i2 - 1 : i2);
			i1 = i2 + sep.length;
		}
		i2 = s.indexOf(equal, i1);
		this.setValue(key, value);
	}
}

/**向map中加入一个key与value的对应,如果value = undefined 则value=null;
  key和value都允许为空,如果map中已经存在了key对应的value则替换原来的value
  并返回旧的value*/
Map.prototype.put = function(key, value) {
	if (isUndefined(value))
		value = null;
	var v = this.elements[key];
	this.elements[key] = value;
	if (isUndefined(v)) { // 是undefined,说明map里面不存在key
		this.len++;
		return value;
	}
	else {
		return v;
	}
}
Map.prototype.push = Map.prototype.put;

/**修改key的名字*/
Map.prototype.renameKey = function(oldKey, newKey) {
	if (this.containsKey(oldKey)) {
		var oldValue = this.removeValue(oldKey);
		if (!this.containsKey(newKey)) { // //如果新的key已经存在,则不覆盖
			this.setValue(newKey, oldValue);
		}
	}
}

Map.prototype.containsKey = function(key) {
	// 使用in运算符的效率
	// 10000个属性查找10000次用时15毫秒
	// 10000个属性查找100000次用时172毫秒
	// 100000个属性查找10000次用时15毫秒
	// 100000个属性查找100000次用时172毫秒
	// return !isUndefined(this.elements[key]);此方法无法正确判断,因为如果加入的数据为put("abc",null),则调用containsKey("abc")返回false
	return key in this.elements;
}

/**
 * 将map中的key与value复制到自己中
 * */
Map.prototype.putMap = function(map) {
	for (var key in map.elements) {
		this.put(key, map.elements[key]);
	}
}

/**
 * 将map中的key和value复制到自己的Map中,忽略key的大小写,以map中的key覆盖当前Map中的key
 * @param {} map
 */
Map.prototype.putMapIgnoreCase = function(map) {
	var keys = this.keySet();
	for (var key in map.elements) {
		/**
		 * 存在相同的key就直接覆盖,如果不存在,那么就查找是否有忽略大小写key相同的项,查找到后删除
		 */
		if(this.contains(key)){
			this.put(key, map.elements[key]);
		}else{
			var idx = keys.indexOfIgnoreCase(key);
			if(idx > -1){
				this.remove(keys[idx]);
			}
			this.put(key, map.elements[key]);
		}
		
	}
}

/**删除一个元素,并且返回这个元素的值*/
Map.prototype.remove = function(_key) {
	var value = this.elements[_key];
	if (isUndefined(value))
		return null;
	delete this.elements[_key];
	this.len--;
	return value;
}

/**返回map中的元素个数*/
Map.prototype.size = function() {
	return this.len;
}
Map.prototype.length = Map.prototype.size;

/**获得一个key对应的值,并返回,如果key不存在,返回null*/
Map.prototype.get = function(_key) {
	var i = 0;
	var value = null;
	if (isNumber(_key)) {
		for (var key in this.elements) {
			if (i++ == _key) {
				value = this.elements[key];
				break;
			}
		}
	}
	else
		value = this.elements[_key];
	return isUndefined(value) ? null : value;
}

/**判断key是否在map中存在*/
Map.prototype.contains = function(_key) {
	var value = this.elements[_key];
	return !isUndefined(value);
}

/**清除map中的所有类容*/
Map.prototype.clear = function() {
	for (var key in this.elements) {
		delete this.elements[key];
	}
	this.len = 0;
}

/**清除map中的所有的key的数组*/
Map.prototype.keySet = function() {
	var keys = new Array();
	for (var key in this.elements) {
		if (!isUndefined(key))
			keys.push(key);
	}
	return keys;
}
Map.prototype.valueSet = function() {
	var rs = new Array();
	for (var key in this.elements) {
		if (isUndefined(key))
			continue;
		var s = this.elements[key];
		rs.push(s);
	}
	return rs;
}

Map.prototype.export2str2 = function(isKey, sep) {
	var arr = new Array();
	for (var key in this.elements) {
		if (isUndefined(key))
			continue;
		if (isKey) {
			arr.push(key);
		}
		else {
			arr.push(this.elements[key]);
		}
	}
	return arr.join(sep ? sep : ";");
}

/**将所有的key和其对应的value导出到返回的字符串中
  key1=value1+separator+key2=value2.....*/
Map.prototype.export2str = function(separator, equal) {
	var arr = new Array();
	var value = "";
	if(!equal) equal = "=";
	for (var key in this.elements) {
		value = key;
		value += equal;
		var s = this.elements[key];
		if (s == null) {
			s = "";
		}
		if (isString(s) && ((s.indexOf(separator) != -1) || (s.indexOf(equal) != -1) || (s.indexOf("\"") != -1))) {
			s = quotedStr(s, "\"");
		}
		value += s;
		arr.push(value);
	}
	return arr.join(separator ? separator : ";");
}

/**将所有的key和其对应的value导出到返回的字符串中
  key1=value1+separator+key2=value2.....*/
Map.prototype.clone = function() {
	var map = new Map();

	map.len = this.len;
	map.separator = this.separator;
	map.equal = this.equal;

	map.elements = {};
	for (var key in this.elements) {
		map.elements[key] = this.elements[key];
	}
	return map;
}

/**将自己的类容变成一个uri的参数串,用utf-8编码*/
Map.prototype.export2uri = function() {
	return this.toString2(null, "&", true);
}

Map.prototype.toString2 = function(equal, separator, encode) {
	var rs = [];
	var value = "";
	if (!equal)
		equal = "=";
	if (!separator)
		separator = ";";
	var length = this.size();
	var cc;
	for (var key in this.elements) {
		value = key;
		value += equal;
		cc = this.elements[key];
		if (cc == undefined || cc == null)
			cc = "";
		value += (!encode ? cc : encodeURIComponent(cc));
		rs.push(value);
	}
	return rs.join(separator);
}

/**返回[[name, value]]数组形式*/
Map.prototype.toArray = function(encode) {
	encode = typeof(encode) == "boolean" ? encode : true;
	var rs = [];
	var s;
	for (var key in this.elements) {
		s = this.elements[key];
		if (!s)
			s = "";
		rs.push([key, !encode ? s : encodeURIComponent(s)]);
	}
	return rs;
}

Map.prototype.getValue = function(key, def) {
	var v = this.get(key);
	return v == null ? def : v;
}

/**获取一个整形值。*/
Map.prototype.getInt = function(key, def) {
	var s = this.getValue(key);
	return s ? parseInt(s) : (def != null ? def : 0);
}

/**获取一个整形值。*/
Map.prototype.getFloat = function(key, def) {
	var s = this.getValue(key);
	return s ? parseFloat(s) : (def != null ? def : 0);
}

/**获得布尔值*/
Map.prototype.getBool = function(key, def) {
	var s = this.getValue(key);
	return parseBool(s, def);
}

Map.prototype.dispose = function() {
}
/**设置此串在此对象中对应的值*/
Map.prototype.setValue = function(key, value) {
	this.put(key, value);
}

/**删除此对象中的key和其对应的值,并返回对应的值,如果没有则返回def*/
Map.prototype.removeValue = function(key, def) {
	var v = this.remove(key);
	if (v == null) {
		return def;
	}
	else {
		return v;
	}
}

/**返回elements*/
Map.prototype.listEntry = function() {
	return this.elements;
};

/**
 * 将map转化成json对象
 * @return jsonobject
 */
Map.prototype.toJson = function() {
	return this.elements;
};

/**
 * 将json对象转换为map
 * @return
 */
Map.prototype.formJson = function(jsonobj) {
	this.clear();
	this.putJson(jsonobj);
};

/**
 * 将json添加到map
 * @return
 */
Map.prototype.putJson = function(jsonobj) {
	for (var key in jsonobj) {
		this.put(key, jsonobj[key]);
	}
};

Map.prototype.toString = function() {
	return this.export2str(this.separator);
};

Map.create = function(json) {
	var map = new Map();
	if (json) map.putJson(json);
	return map;
};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript中,有多种方法可以实现拷贝。以下是几种常见的方法: 1. 使用JSON对象:你可以使用`JSON.stringify()`将对象转换为字符串,再使用`JSON.parse()`将字符串转换为新的对象,从而实现拷贝。但是这种方法存在一些问题,比如无法拷贝函数、undefined和symbol等数据类型。 2. 递归实现:递归方法是一种常见的拷贝方式。通过递归遍历对象的每个属性,创建一个新的对象并将属性值赋给新对象的对应属性。这种方法可以处理多种类型的数据,但无法拷贝一些特殊对象(如`new Map()`)。 3. 使用jQuery的extend方法:jQuery的`$.extend()`方法提供了拷贝的功能。通过设置第一个参数为`true`,可以实现拷贝。但需要注意,这种方法需要引入jQuery库。 4. 使用lodash库的_.cloneDeep方法:lodash库提供了一个名为`_.cloneDeep()`的方法,可以实现拷贝。这个方法可以拷贝对象和数组的内部数据实体,并重新分配内存空间存储数据。 需要注意的是,拷贝会创建一个新的对象,并在内存中分配新的空间来存储数据实体。而浅拷贝只是复制了引用类型的指针,副本和原对象指向同一个内存。因此,在拷贝对象时,需要根据实际需求选择适当的方法。 所以,以上就是几种常见的JavaScript实现拷贝的方法。每种方法都有其适用的场景和限制,你可以根据具体的需求选择合适的方法来实现拷贝。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [JS拷贝的几种实现方法](https://blog.csdn.net/weixin_46574499/article/details/125464997)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值