今天重新看了一遍JS高程的第一到四章,查漏补缺记录了一些容易出错的地方,做笔记如下:
变量的作用域问题
1 | function test(){ |
变量未声明,且循环定义的循环变量,都是在全局的作用域中。
typeof()方法
1 | var message; |
注:Null类型表示一个空对象指针,因此使用typeof检测时会返回object。(undefined派生自Null,因此二者相等)
NaN与任何值都不相等,包括NaN本身
Number()方法进行数值转换
1 | var num3 = Number(0xa); //10 |
按位操作(根据数值的二进制进行操作)
1 | var result1 = 3 & 1; |
变量的赋值技巧
1 | var num = num1 || num2; |
当num1有值是,num被赋值为num1,否则被赋值为num2.
switch操作符
switch的语句中可以使用任何数据类型,这在其他的很多语言中是没有的,且switch支持表达式。
注:switch使用的是全等操作符,因此“10”和10 是不相等的。
arguments[]对象
arguments[]对象可在函数调用时使用,arguments[0]表示第一个参数,arguments[1]表示第二个参数,以此类推。1
2
3
4
5function anyArgs(){
console.log(arguments.length);
}
anyArgs("string",1); //2
anyArgs(); //0
JS方法不存在重载,因此不可同时var两个相同函数名的函数
基本类型和引用类型的变量赋值
基本类型:相当于在堆中创建了一个新空间,并在该空间中为新变量赋予相同的值。1
2
3
4var num1 = 5;
var num2 = num1;
num1 = 4;
console.log(num2); //5
引用类型:在堆中的引用空间是不变的,新的变量值与老的变量值指向同一个堆空间。1
2
3
4var obj1 = new Object();
var obj2 = new Object();
obj1.name = "Changer";
console.log(obj2.name); //Changer
传参问题
向参数传递基本类型值时,被传递的值会被复制给一个局部变量,其本身的值及属性不会改变。1
2
3
4
5
6
7
8var num1 = 1;
function count(num){
num++;
return num;
}
count(num1);
cinsole.log(num1); //1
console.log(count(num1)); //2
当给引用类型传参时,引用类型变量传递到函数中会复制到变量中,在函数内部,变量和引用类型常量实际上引用的是同一个对象,因此在函数内部为常量添加属性后,在外也可调用。(这句话,我有点儿没看懂)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function setName(obj){
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
console.log(person.name); //Nicholas
//另有一例,用于说明局部变量的传参问题
function setName(obj){
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
setName(person);
console.log(person.name); //Nicholas
//原因:局部变量作用域仅在函数中,使用后即被销毁。
延长作用域链
1 | function buildUrl(){ |
此函数有效,原因(个人认为)S函数无块级作用域,因此可在with外调用。
JS的垃圾回收机制
标记清除
当变量进入环境时,就将这个变量标记为“进入环境”状态,当变量离开环境时,则将其标记为“离开环境”状态,它会去掉环境中的变量及被环境中变量引用的变量的标记。大部分浏览器采用此策略。
引用计数
跟踪记录每个值被引用的次数,当声明了一个变量并将一个引用类型值赋值给该变量时,该值的引用次数则为1,当再次被引用时加一,相反,当引用的变量取消引用时,减一,减为0后将被回收。
但是该方法存在一个很严重的性能问题:1
2
3
4
5
6function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.otherObject = objectB;
objectB.anotherObject = objectA;
}
运行上例时,其引用次数将永远不为0,若此函数被大量调用,则其垃圾将永远不会回收。
解决方案(这也是采用标记清除方法的垃圾回收最佳方案):当不需要使用该变量时,为其设置值为null。1
2objectA.otherObject = null;
objectB.anotherObject = null;
另:在IE中,可食用window.CollectGarbage()方法立即执行垃圾回收。