js变量 作用域与内存
前言
这是我人生中的第一篇文章,用作记录我读《jsvascript高级程序设计》,也就是红宝书,内容基础不会太深入研究。
原始值和引用值
在js中有六种原始值分别是(Undefined Null Boolean Number String和Symbol)原始值和引用值最为显著的区别就是访问方式的不同,原始值的变量是按值访问的也就是在操作原始值时候会直接操作变量的实际值,而引用值在操作对象的时候是操作的对象的引用而非对象本身也就是如图
在操作b的时候会通过b的引用访问到b的实际值,通过引用间接操作,这个概念对于下文的理解非常重要
原始值的创建区别
原始值有两种创建方式一种是通过new关键字创建,另一种是直接通过字面量创建
javascript
let str = new String("xxk");//new 关键字创建
let str1 = "ddd";//字面量创建
str1.age = 18;
cansole.log(str1.age)//undefined
可以在上面的代码中看出通过字面创建的字符串添加属性并不会报错在下面访问会是undefined,js中只有引用值可以动态添加后面可以使用的属性,使用new关键字会直接创建一个Object的对象
参数的传递
变量的传递有两种方式 按值传递和按引用传递 在js中几乎所有的赋值都是按值传递(模块化导出模块是按引用传递)两种传递的值有什么不一样吗?
按值传递的时候变量的值会被直接的复制一份,并复制给新的变量,在函数的参数传递的时候值会被复制到一个局部变量(也就是arguments对象的一个槽位),这意味着对于本地变量的修改不会反应到外部函数
javascript
function add(num){
num+=10;
return num;
}
let count = 20 ;
let res = add(count);
cansole.log(count);//20
cansole.log(res); //30
上面代码发现在函数内部的变量改变并不会影响函数传递的参数的值,这是基本数据类型,而引用类型由于他们的访问方式有所不同,结果也有所不同
javascript
function test(obj){
obj.name = "xxk";
return obj;
}
let person= new Object();
test(person);
console.log(person.name);// xxk
上面代码中将person变量传递给test函数,在局部作用域给obj添加了一个name的属性,为什么person会有name这个属性呢,这不是和上面说的不会改变函数外部的值自相矛盾了吗?事实究竟是怎么样呢?还记的上面第一节简绍的对象的访问方式吧
上图给出了解释,由于person存储的值为内存地址的引用,当person赋值给obj的时候person的引用会被复制一份给obj,他们的值(也就是引用)相同他们指向的是同一块物理地址,也就是说在操作obj的时候会根据引用操作到Object,而person也有相同的引用指向相同的地址,这也就是为什么obj的改变会引起person的改变
按引用传递:
由名字可以看出变量传递的时候是按引用传递的,也就是直接把地址复制一份,并复制给另一个变量,两个变量拥有着相同的地址
那如何证明js是按值传递而不是按引用传递的呢?
javascript
function setname(obj){
obj.name = "xxk";
obj = new Object();
obj.name = "djy"
return obj;
}
let person= new Object();
test(person);
console.log(person.name);// xxk
在上面的代码中obj被赋值给一个新的对象,并将name属性改为了djy,但是person的name打印出来的name是name。如果js是按照引用传递的话,person与obj都是相同的地址,obj改变了地址也会反应到person变量上面,person.name的值应为djy,但是是xxk,所以说js是按照值传递。
下一章
js的上下文,作用域链以及垃圾回收