红皮书第四章总结

290 阅读2分钟

先记录第四章,回头别忘了补上前三章

一、基本类型和引用类型的值

  1. 类型:变量的值分为基本类型值和引用类型值,基本类型值即简单的数据段(UndefinedNullBooleanNumberString),引用类型值则指那些可能由多个值构成的对象(ArrayObject等);
  2. 赋值:定义以上两种值的方式是类似的,都是创建一个变量并为其赋值,例如var a = 1var obj = new Object(),当值的类型为基本类型时,变量存储的是当前基本类型值。但是当值的类型为引用类型时,变量存储的是一个指向内存中引用类型值地址的一个指针;
  3. 复制:对于基本类型值的复制,会新创建一个值,并赋值给新的变量上。而对于引用类型值的复制,则是将指向内存中引用类型值地址的指针赋值给新的变量。
  4. 传参: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。