JavaScript的数据类型

简单数据类型

  1. string
  2. number
  3. boolean
  4. function
  5. null
  6. undefined

复杂数据类型

  1. String
  2. Number
  3. Boolean
  4. Function
  5. Date
  6. Array
  7. RegExp
  8. Object

各种类型的深复制方式:

先来看看简单类型的复制方式:

//string
var s1 = 'abc';
var s2 = s1;
s2 = 'ccc';
console.log(s1); //number
var n1 = 12.1;
var n2 = n1;
n2 = 7410;
console.log(n1); //boolean
var b1 = true;
var b2 = b1;
b2 = false;
console.log(b1); //null
var nu1 = null;
var nu2 = nu1;
nu2 = 'abc';
console.log(nu1); //undefined
var u1 = undefined;
var u2 = u1;
u2 = 'abc';
console.log(u1);

从以上的代码可以看出,简单类型,只需要直接赋值就是深复制了。但是也有一个例外,那就是function。

接着来看看String、Number、Boolean、Date的深复制:

//String
var s1 = new String('s1');
var s2 = new String(s1);
console.log(s2); //Number
var n1 = new Number('1');
var n2 = new Number(n1);
console.log(n2); //Boolean
var b1 = new Boolean(1);
var b2 = new Boolean(b1);
console.log(b2); //Date
var d1 = new Date();
var d2 = new Date(d1);
console.log(d2);

除以上的做法之外,还需要对实例属性进行拷贝。那么剩下的Function、function、RegExp和Array还有Object又该怎么拷贝呢?这几个比较特殊,我们一个一个来:

对于Function和function的深拷贝,我们可以按照如下的方式来做:

var f1 = new Function('a', 'console.log("f1" + a);');
var f2 = function(b){console.log('f2' + b);}; //通过toString获取源代码(有浏览器兼容问题)
var code = f1.toString();
//利用eval进行复制
var f1_copy = (function(functionCode){
eval('var f = ' + functionCode);
return f;
})(code); f1_copy('abc'); //当然f2也可以用同样的方式来复制。

接着,我们来看下RegExp,可以同样同时eval来执行拷贝,也可以使用如下方式:

var reg1 = /abc/g;
var reg2 = new RegExp('abc', 'gmi'); var reg1_copy = (function(reg){
var pattern = reg.valueOf();
var flags = (pattern.global ? 'g' : '') +
(pattern.ignorecase ? 'i' : '') + (pattern.multiline ? 'm' : '');
return new RegExp(pattern.source, flags);
})(reg1);

最后,我们来说一说Array的复制,有的人可以说,直接用slice复制一份出来就是了,那我们来看看,是否真的达到效果的呢?

var o = {name: 'Jay'};
var arr1 = [o, '22', 1];
var arr2 = arr1.slice(0);
arr2[0].name = 'Arr2';
console.log(arr1[0].name);

很简短的代码,直接就把slice抛弃了,slice只能保证Array是新的,并不意味着内部的元素是深拷贝的,那么如何做呢?就是遍历元素,对每个元素进行深拷贝了。代码如下:

var o = {name: 'Jay'};
var arr1 = [o, '22', 1]; var arr2 = [];
for(var i = 0, len = arr1.length; i < len; i++){
//注意,deepClone还未实现
arr2.push(deepClone(arr1[i]));
}

以上对针对不同的类型,特殊的代码,那么如何来拷贝实例属性呢?代码如下:

var o = {p1: '1', p2: 2, p3: function(){}};

var copy = {};
for(var p in o){
//注意deepClone还未实现
copy[p] = deepClone(o[p]);
}

注意:针对复杂类型,还需要同时copy.constructor = source.constructor来保证构造函数一致。

最终的深复制代码

通过以上的分析与代码示例,那么我们最终的代码又是怎样的呢?详细代码如下:

//自调用函数,防御性编程
;
(function (window) {
'use strict'; function getCustomType(obj) {
var type = typeof obj,
resultType = 'object';
//简单类型
if (type !== 'object' || obj === null) {
resultType = 'simple';
} else if (obj instanceof String || obj instanceof Number || obj instanceof Boolean || obj instanceof Date) {
resultType = 'complex';
} else if (obj instanceof Function) {
resultType = 'function';
} else if (obj instanceof RegExp) {
resultType = 'regexp';
} else if (obj instanceof Array) {
resultType = 'array';
}
return resultType;
} function cloneProperties(dest, source) {
dest.constructor = source.constructor;
for (var p in source) {
dest[p] = deepClone(source[p]);
}
return dest;
} function cloneSimple(obj) {
return obj;
} function cloneComplex(obj) {
var result = new obj.constructor(obj);
return cloneProperties(result);
} function cloneFunction(obj) {
var funCopy = (function (f) {
eval('var abcdefg_$$$$ = ' + obj.toString());
return abcdefg_$$$$;
})(obj);
return cloneProperties(funCopy);
} function cloneRegExp(obj) {
var pattern = obj.valueOf();
var flags = (pattern.global ? 'g' : '') +
(pattern.ignorecase ? 'i' : '') + (pattern.multiline ? 'm' : '');
var reg = new RegExp(pattern.source, flags);
return cloneProperties(reg);
} function cloneArray(obj) {
var resultArr = [];
for (var i = 0, len = obj.length; i < len; i++) {
resultArr.push(deepClone(obj[i]));
}
for (var p in obj) {
if (typeof p === 'number' && p < len) {
continue;
}
resultArr[p] = deepClone(obj[p]);
}
return resultArr;
} function cloneObject(obj) {
var result = {};
result.constructor = obj.constructor;
for (var p in obj) {
result[p] = deepClone(obj[p]);
}
return result;
} function deepClone(obj) {
var f = undefined;
switch (getCustomType(obj)) {
case 'simple':
f = cloneSimple;
break;
case 'complex':
f = cloneComplex;
break;
case 'function':
f = cloneFunction;
break;
case 'regexp':
f = cloneRegExp;
break;
case 'array':
f = cloneArray;
break;
case 'object':
f = cloneObject;
break;
}
return f.call(undefined, obj);
} //挂载到window对象上
window.deepClone = deepClone;
})(window);

*:first-child {
margin-top: 0 !important;
}

body>*:last-child {
margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
font-size: inherit;
}

h1 {
font-size: 28px;
color: #000;
}

h2 {
font-size: 24px;
border-bottom: 1px solid #ccc;
color: #000;
}

h3 {
font-size: 18px;
}

h4 {
font-size: 16px;
}

h5 {
font-size: 14px;
}

h6 {
color: #777;
font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
color: #4183C4;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
padding-left: 30px;
}

ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}

dl {
padding: 0;
}

dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}

dl dt:first-child {
padding: 0;
}

dl dt>:first-child {
margin-top: 0px;
}

dl dt>:last-child {
margin-bottom: 0px;
}

dl dd {
margin: 0 0 15px;
padding: 0 15px;
}

dl dd>:first-child {
margin-top: 0px;
}

dl dd>:last-child {
margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}

pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}

pre code, pre tt {
background-color: transparent;
border: none;
}

kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}

blockquote>:first-child {
margin-top: 0px;
}

blockquote>:last-child {
margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}

/* IMAGES
=============================================================================*/

img {
max-width: 100%
}
-->

JavaScript的深拷贝的实现的更多相关文章

  1. javascript对象深拷贝,浅拷贝 ,支持数组

    javascript对象深拷贝,浅拷贝 ,支持数组 经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One meth ...

  2. javascript浅拷贝深拷贝理解记录

    javascript的深拷贝和浅拷贝问题几乎是面试必问的问题.好记性不如烂笔头,特此来记录一下自己对深拷贝浅拷贝的理解. 顾名思义,拷贝就是copy复制,在js中可以浅而理解为对一个对象或者数组的复制 ...

  3. JavaScript实现深拷贝(深复制) 面试题

    1.两种方法实现深拷贝(深复制) (1)方法一:兼容性好,请仔细看代码(网上大部分代码有Bug) (2)方法二:需要对象满足JSON数据格式.JOSN数据格式:http://www.cnblogs.c ...

  4. JavaScript中深拷贝实现

    JavaScript 中深拷贝实现   拷贝时候涉及到: 1.循环结构 2.判断数组 Array 还是对象 Object   函数实现 /** * 获取满足条件的数组中的第一个元素 * @param ...

  5. 也来玩玩 javascript对象深拷贝,浅拷贝

    经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...

  6. 【javascript】浅谈javaScript的深拷贝

        前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...

  7. JavaScript之深拷贝和浅拷贝

    前言 工作中会经常遇到操作数组.对象的情况,你肯定会将原数组.对象进行‘备份’当真正对其操作时发现备份的也发生改变,此时你一脸懵逼,到时是为啥,不是已经备份了么,怎么备份的数组.对象也会发生变化.如果 ...

  8. javascript浅拷贝深拷贝详解

    一.浅拷贝 浅拷贝在现实中最常见的表现在赋值上面,例如 <!DOCTYPE html> <html lang="en"> <head> < ...

  9. 【javascript】详解javaScript的深拷贝

        前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...

随机推荐

  1. 针对远程Git代码库使用SSH公匙

    → 运行Git Bash→ 创建SSH公匙和私匙ssh-keygen -t rsa→ 输入SSH公匙存放文件,选择使用默认的,按Enter→ 如果已经存在,提示是否重写,输入n,按Enter→ 打开C ...

  2. Revit中如何控制图元的显示与隐藏

    Revit建模过程中经常会遇到图元的相互遮挡的情况,为了将一些图元显示出来,就需要将一些不需要显示的图元隐藏掉,这就需要用到"隐藏/重置"工具,在Revit绘图窗口左下角提供了一排 ...

  3. GitHub前50名的Objective-C动画相关库

    GitHub的Objective-C的动画UI库其实是最多的一部分,GitHub有相当一部分的动画大牛,如Jonathan George,Nick Lockwood,Kevin,Roman Efimo ...

  4. J2EE Web开发入门—通过action是以传统方式返回JSON数据

    关键字:maven.m2eclipse.JSON.Struts2.Log4j2.tomcat.jdk7.Config Browser Plugin Created by Bob 20131031 l ...

  5. Flask-Babel 中文支持(zh-CN和zh-Hans-CN)

    命名的翻译文件夹必须命名为zh_Hans-CN,其他的都是不标准的命名!

  6. [数据库]SQL Server 用户NT AUTHORITY\IUSR 登录失败

    今天打开网站时,突然报这个错误,平时都好好的 Cannot open database "JMECC" requested by the login. The login fail ...

  7. mssql中sp_executesql的用法

    上图:

  8. 为什么 NSLog 不支持 Swift 对象(转)

    https://segmentfault.com/a/1190000005668218 也就说: 1. 如果是 OC 的对象,重写 description 的 get 方法就可以了. 2. 如果不是 ...

  9. 【网络编程】——linux socket demo

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/socket ...

  10. Java IO--压缩流

    压缩流: 压缩流的实现: zipEntry: 在实例化ZipEntry的时候,要设置名称,此名称实际上就是压缩文件中的每一个元素的名称. ZipOutputStream: import java.io ...