JS数据类型按值传递以及引用传递

JS数据传递方式

  js本身是弱类型语言,不像Java这些强类型语言,对于一个变量,我们可以给他赋任何类型的值,但是在赋值的过程中,我们发现js赋值有两种方式: 按值传递 引用传递

按值传递类型

1
2
3
4
5
var a=1;
var b=a;
b=3;
console.log(a);//输出1
console.log(b);//输出3,改变b的值,不会改变原始a的值

  像基本数据类型赋值都是按值传递,包括undefined,null,Boolean,Number,String.

引用传递类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var a={
name : 'bob'
};
var b=a; //这里其实是把a的引用地址赋值给了b,a和b指向的是同一个对象
b.name = 'John';
console.log(a);//输出{name: 'John'}
console.log(b);//输出{name: 'John'}
如果改成
var a={
name : 'bob'
};
var b={}; //b创建了一个新的对象引用
b.name = a.name;
b.name = 'John'
console.log(a);//输出{name: 'bob'}
console.log(b);//输出{name: 'John'}

  这里的Object就是复杂数据类型。
  最近在项目的新框架中经常遇到变量改变而影响到模板渲染的另一个变量,导致渲染出错,所以这里把这个问题重新提出来,并贴上常使用深拷贝的方法。

  简单版,日常够用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
*target 拷贝对象
*inner 内部使用,不用传参
*/
function deepCopy(target, inner) {
var inner = inner || {};
for (var i in target) {
if (typeof target[i] === 'object') {
inner[i] = (target[i].constructor === Array) ? [] : {};
deepCopy(target[i], inner[i]);
} else {
inner[i] = target[i];
}
}
return inner;
}

  下面是stackoverflow的完整版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* 深拷贝任意类型对象
* 参考修改自http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript/25921504
* 支持:值类型、普通对象、数组、日期、正则表达式、DOM
* @param src 要拷贝的对象
* @param _visited 内部使用,不用传参!
* @returns {*} 传入的对象的副本
*/
function deepCopy(src, /* INTERNAL */ _visited) {
if(src == null || typeof(src) !== 'object'){
return src;
}
if (_visited == undefined){
_visited = [];
}
else {
var i, len = _visited.length;
for (i = 0; i < len; i++) {
// If src was already visited, don't try to copy it, just return the reference
if (src === _visited[i]) {
return src;
}
}
}
_visited.push(src);
if(typeof src.clone == 'function'){
return src.clone(true);
}
//Special cases:
//Array
if (Object.prototype.toString.call(src) == '[object Array]') {
//[].slice(0) would soft clone
ret = src.slice();
var j = ret.length;
while (j--){
ret[j] = deepCopy(ret[j], _visited);
}
return ret;
}
//Date
if (src instanceof Date){
return new Date(src.getTime());
}
//RegExp
if(src instanceof RegExp){
return new RegExp(src);
}
//DOM Elements
if(src.nodeType && typeof src.cloneNode == 'function'){
return src.cloneNode(true);
}
//If we've reached here, we have a regular object, array, or function
//make sure the returned object has the same prototype as the original
var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
if (!proto) {
proto = src.constructor.prototype; //this line would probably only be reached by very old browsers
}
var ret = Object.create(proto);
for(var key in src){
if (Object.prototype.hasOwnProperty.call(src, key)) {
ret[key] = deepCopy(src[key], _visited);
}
}
return ret;
},

坚持原创技术分享,您的支持将鼓励我继续创作!