验证JavaScript函数“按参数传递”特性引发的思考
俗话说,“书读百遍,其义自见”。阅读专业性的书籍更是需要不断去啃,直到读懂,完全理解为止。
之前看了好几遍《JavaScript高级程序设计》,每看一遍都觉得好像对JavaScript这门语言有了更深层次的理解。
这次看到本书的“4.1 基本类型和引用类型的值”这一章节的时候,又忍不住动手验证了一下代码。结果对JavaScript这门语言,有了一系列更深层次的理解。
以下是原书给出的案例:
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
可以看出来,传入一个对象以后,如果不是按值传递的,那么person.name
的值就不会是Nicholas
了,而是Greg
了。
当然我的思考不仅仅局限在这里,我把demo改了以下,变成下面这样:
function testArg(object){
object.name = "Jay";
var object = new Object();
object.name = "Michael";
return object.name;
}
var person = new Object(); //定义对象
var str = "string"; //定义字符串
var number = 34; //定义数字
var boolean = true; //定义布尔值
console.log(testArg(number)); //Michael
console.log(number.name); //undefined
console.log(testArg(boolean)); //Michael
console.log(boolean.name); //undefined
console.log(testArg(str)); //Michael
console.log(str.name); //undefined
console.log(testArg(true)); //Michael
console.log(true.name); //undefined
console.log(testArg(person)); //Michael
console.log(person.name); //Jay
本来需要接受对象的地方,你传入字符串、数字和布尔值进去竟然不报错。
但是当你改成下面这样,就会报错了:
function testArg(object){
object.name = "Jay";
var object = new Object();
object.name = "Michael";
return object.name;
}
var a = undefined; //未定义
var b = null; //空
console.log(testArg(number)); //报错
console.log(number.name); //报错
然后我就很迷惑,为什么字符串、数字和布尔值也能够添加属性而不报错,但是添加完了以后,你查询对应的属性的时候,就变成undefined了。
后来还是在《JavaScript高级程序设计》这本书上找到了合理的解释:
原来是因为Boolean、Number和String是三个特殊的引用类型,JavaScript定义这三个基本包装类型的目的是为了让我们拥有一些方法来操作数据。
但是基本包装类型的特点是:(以下为引用)
引用类型与基本包装类型的主要区别就是对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。
PS:如果有兴趣的童鞋,可以去详细阅读《JavaScript高级程序设计第三版》这本书的5.6章节。