(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)
(注2:更多内容请查看我的目录。)
1. JS的数据类型
JS变量的数据类型的值有两种:基本类型值和引用类型值。基本类型值指简单的数据段,而引用类型值指那些可能由多个值构成的对象。
基本类型值有以下五种:Undefined、Null、Boolean、Number和String。引用类型值即保存在内存中的对象。
var num1 = 1;
var str1 = '1';
1.1基本类型
var obj1 = {a: 1};
1.2引用类型
2. JS的变量复制
JS对基本类型的复制和引用类型的复制并不相同。基本类型值的复制实际上将变量和其存储的内容重新复制了一份,而引用类型的复制只是将其保存的指针复制了一份,实际存储对象的堆并没有复制。
var num1 = 6;
var num2 = num1;
2.1基本类型复制
var obj1 = {a: 1};
var obj2 = obj1;
2.2引用类型复制
3. JS的参数传递是按值传参
JS的参数是按值传递,即将函数外部的值复制给函数内部的参数,其复制过程如前所述。那么对内部变量值的改变是否会影响外部变量呢,这里我们用具体的例子来分析一下。
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); //20 没有改变
alert(result); //30
我们可以看到,基本类型变量的传参对原变量并无影响,这一点大家也容易理解。可是对引用类型的传参呢?
// eg3.1
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
我们发现原始变量person对象的name属性被改变了,这具有很强的迷惑性,会让人以为引用类型的传参是将整个引用对象存储的内容复制传递了。是否如此呢?我们看下面这个例子。
// eg3.2
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
如果真的是按引用传递,那么最后person.name应该是'Greg'才对,但事实上却是'Nicholas',说明这里是并不是按引用传递。下面我们来一步步分析这两段代码的实际过程。
对于eg3.1和eg3.2:
step1: var person = new Object();执行完如下:
step1
step2: 进入setName(person);如下:
step2
step3: obj.name = "Nicholas";执行完如下:
step3
eg3.1的setName函数调用到此已结束,此时,person.name从图中可以看出是'Nicholas'。而对于eg3.2,其setName函数增加了两个步骤,如下:
step4: obj = new Object();执行完如下:
step4
step5: obj.name = "Greg";执行完如下:
step5
可以看到,此时person.name仍然是'Nicholas'。
现在,我们明白了,其实JS函数参数的传递始终是按值传递。但是在函数调用的过程中,我们到底是对该值指向的堆地址进行了操作,还是对该值进行了操作,决定了我们是否会对原变量产生影响。
4. 测试一下
看到这里,你应该已经掌握了JS的数据类型和按值传递。来做一个小测验,下面是两个对数组进行拼接并返回拼接后数组的函数,哪个函数在拼接的同时对传入的参数也产生了影响呢?(顺便学习一下es6的知识吧b( ̄▽ ̄)d)
var fillArray = (arr, ...values) => {arr.push(...values);return arr;}
var fillArray = (arr, ...values) => {arr = arr.concat(...values);return arr;}
参考
BOOK-《JavaScript高级程序设计(第3版)》 第3章
网友评论