先记录第四章,回头别忘了补上前三章
一、基本类型和引用类型的值
- 类型:变量的值分为基本类型值和引用类型值,基本类型值即简单的数据段(Undefined、Null、Boolean、Number、String),引用类型值则指那些可能由多个值构成的对象(Array、Object等);
- 赋值:定义以上两种值的方式是类似的,都是创建一个变量并为其赋值,例如
var a = 1、var obj = new Object(),当值的类型为基本类型时,变量存储的是当前基本类型值。但是当值的类型为引用类型时,变量存储的是一个指向内存中引用类型值地址的一个指针; - 复制:对于基本类型值的复制,会新创建一个值,并赋值给新的变量上。而对于引用类型值的复制,则是将指向内存中引用类型值地址的指针赋值给新的变量。
- 传参:ECMAScript中所有函数的参数都是按值传递的。形参不过是函数内部定义了一些局部变量,将传入的值赋值给了这些局部变量。
举个栗子:
function addNum(num){
num += 10;
return num;
}
var count = 10;
var result = addNum(count);
console.log(count); // 10
console.log(result); // 20
function setName(obj){
obj.name = "zhangsan";
}
var person = new Object();
setName(person);
console.log(person.name); // "zhangsan"
第一个函数中有一个形参num,这其实是函数的局部变量,它负责接收外部传来的count的值,而最后return出去的,也只是这个局部变量的值。
第二个函数一样,是一个名为obj的局部变量,指向了外部传来的person的值在内存中的地址,由于内部obj和外部的person指向的都是同一个内存地址,所以内部对这个地址的对象做了操作,同时提现到person中。为了证明函数是按值传递的,我们改进一下第二个函数。
function setName(obj){
obj.name = "zhangsan";
obj = new Object();
obj.name = "lisi";
}
var person = new Object();
setName(person);
console.log(person.name); // "zhangsan"
这里多添加了两行代码,如果是按引用传递的,那么person的指向就应该是新建的属性name是lisi的这么一个对象,但是实际打印出来,person对象的name依然是zhangsan,可见函数确实是按值传递的。
那么如何验证函数形参是函数的局部变量呢?很简单
function foo(obj){
const obj = 1;
}
// Uncaught SyntaxError: Identifier 'obj' has already been declared
在同一作用域下,let,const定义多次会报错,所以直接体现了obj是函数内部的局部变量。
5. 检测:typeof用来检测String,Number,Boolean,Undefined最合适不过,如果检测对象是一个对象或者null,那么typeof返回的就是一个“object”。而对引用类型进行判断,则需要用到instanceof,例如person instanceof Object,返回值是一个Boolean。