这是我参与新手入门的第3篇文章。
前言
本文内容主要是关于红宝书第四章的内容,包括原始值与引用值,执行上下文相关知识,及js的垃圾回收机制。依然是以拾遗为主,对一些老生常谈的知识点不再赘述。本次我打算调整下形式,以代码为切入点,引出相关的原理。
动态属性
let name1 = 'Jack';
let name2 = new String('Rose');
name1.age = 22;
name2.age = 24;
console.log(name1.age); // undefined
console.log(name2.age); // 24
console.log(typeof name1); // string
console.log(typeof name2); // object
复制代码
上述代码中,虽然name1
和name2
虽然看上去都是字符串。但对于原始类型的变量,若使用new
关键字创建,JavaScript
会创建一个Object
类型的实例,但其行为类似原始值。 因此,这两个对象分别是不同的数据类型,原始值的字符串不能追加属性,引用值的对象可以追加属性。
传递参数
ECMAScript
中所有函数的参数都是按值传递的。
function addTen(num) {
num += 10;
return num;
}
let count = 20;
let result = addTen(count);
console.log(count); // 20
console.log(result); // 30
复制代码
如上代码,由于参数是按值传递,所以函数的参数num
和count
的值互不干扰,修改num
的值并不会引起函数外部count
的值改变,他们两个唯一的关系,就是一开始两个变量保存的值相同。
在按值传递参数时,参数的值被复制给了函数的一个局部变量。这个行为在上例中很好理解,但当参数是对象时,就有些迷惑了。如下:
function setName(obj) {
obj.name = "Jack";
obj = new Object();
obj.name = "Rose";
}
let person = new Object();
setName(person);
console.log(person.name); // Jack
复制代码
上述代码可能很难理解。person
作为参数传给函数后,参数obj
复制了person
的值。当执行obj.name="Jack"
时,obj
和person
都指向同一个外部对象,因此person
被添加了name
这个属性。但当obj
被赋值了一个新的对象时,改变的只是obj
的指针,它指向了一个本地对象,这个对象在函数执行结束时就被销毁了。
上边两组代码,若参数是按引用传递的,那count
的值会变成30,person
的指针会指向新创建的对象,即person.name
变为"Rose"
。
变量声明
function add(num1, num2) {
sum = num1 + num2;
return sum;
}
let result = add(10, 20);
console.log(sum);
复制代码
变量sum
未使用关键字声明,因此在函数调用后,sum
被添加到了全局上下文,在函数退出后仍然能被访问到。这样的写法是需要严格禁止的。
由于
const
声明暗示变量的值是单一类型且不可修改,JavaScript
运行时编译器可以将其所有实例都替换成实际的值,而不会通过查询表进行变量查找。谷歌的V8引擎就执行这种优化。
应尽可能地多使用const
声明。
垃圾回收
这一部分内容还是了解为主,JavaScript
使用标记清理的回收算法。
前端开发者在垃圾回收这一块儿能做的比较少。如通过const
和let
声明提升性能,因为块级作用域可能会更早的让垃圾回收程序介入,尽早回收内存;另外,通过将全局对象、全局对象的属性和循环引用在不需要时设置为null
,解除引用,也有利于垃圾回收。
后记
本次笔记内容不多,比较难理解的应该还是参数传递那一部分。虽然工作中似乎并未因此写过bug,但也从没注意过这里边的区别。个人感觉基础知识中可挖掘的点还是很多的,对于这些知识点的学习与掌握,也能够加深对以后知识的理解。