变量
js的变量是松散性的,非强制性的。(在特定的情况是一种特定的类型)。
基本类型和引用类型的值
基本类型的值:保存在栈内存的简单数据段,这种值完全保存在内存中的一个位置
引用类型的值:保存在对内存中的对象,变量中保存的其实是一个指针。
基本类型的值有:undefined null boolean number string在内存中的空间的大小是一个定值,是按值来访问。
引用类型的值:Array Object 这种类型的大小不固定。所以将引用数据类型放在堆内存中, 它的地址是存放在栈内存中的。引用数据类型是按引用访问的。
动态属性
可以为引用数据类型动态添加属性,但是不可以为基本数据类型动态添加属性
var cc="sasa";
cc.age=12;
console.log(cc);
console.log(cc.age); //undefined\
var bb=new Object();
bb.age="sa";
console.log(bb.age); //sa
复制变量值
基本类型复制的是数据 导致两个变量是独立的,操作互不影响
引用类型的数据复制的是地址
所以不管是基本数据类型还是引用数据类型复制的都是栈内存中的数据,不能复制堆内存中的数据
基本数据类型的复制,两个不不干扰的版本
var bb=11;
var cc=bb;
cc=12;
console.log(cc); //12
console.log(bb); //11
引用类型的复制,复制 的是一个地址,复制后的对象和原来的对象是一个
var bb={name:"saa"};
var cc=bb;
cc.name="bvv";
console.log(cc.name); //bvv
console.log(bb.name); //bvv
两种数据类型的传递参数
ECMA中所有的函数参数都是按值传递,没有按引用传递
function sun(num) {
return num+10;
}
var cc=50;
console.log(sun(cc)); //60
console.log(cc); //依然是50
但是参数可以传递以一个引用类型的数据
function sun(obj) {
obj.name="sa";
}
var cc=new Object();
sun(cc);
console.log(cc.name); //sa
因为其实传进来的其实是一个地址,但是这种方式的传递不是按引用传递
检测类型
typeof运算符 不能检测出是什么对象 知识可以检测基本数据类型
如果想要区分是哪一种对象的话,就使用instanceof
var cc=[1,3,5];
console.log(cc instanceof Array); //true
两种生成字符串的方式,但是不同的类型,相同的值
var dd="sa";
console.log(typeof dd);
var mm=new String("sa");
console.log(typeof mm); //string
console.log(mm instanceof String); //true
执行环境及作用域
每一个执行环境中的都有与之关联的变量对象(this或者window),就好比全局的window对象可以调用方法和属性
function cc() {
return 111;
}
console.log(cc()); //111
console.log(window.cc()); //111
作用域仅限制在函数体内这个局部的环境中。。
通过传递参数,可以替换函数体内的局部变量,但作用域仅限制在函数这个局部环境的变量中。每一个函数在被调用的过程中都会创建自己的执行环境,当执行这个函数的时候,函数就会被推到环境栈中去执行,而且执行后又在环境栈中弹出,把控制权交给上一级的执行环境
没有块级作用域
if语句的花括号没有块级作用域
if(true){
var bb="sas";
}
console.log(bb); //sas
for语句的花括号也没有块级作用域
for(var i=0;i<10;i++){
console.log(i);
}
console.log(i) //外边可以访问到i
但是针对函数的花括号则有块级作用域,函数内部使用var申明的变量,外部不会访问到。
内存问题
所有变量在使用完之后都会回收,js会自动回收。会自行的管理内存。
js中最常用的垃圾回收收集方式就是标记清除,垃圾收集器会在运行的时候给存储在内存中的变量加上标记。然后,他会去掉环境中正在使用的变量的标记,而没有额比标记的变量将被视为准备删除的空间。垃圾回收器是周期运行的。