JS高程读书笔记《一》

219 阅读4分钟

JS的基本数据类型

  • 基本数据类型:UndefinedNullBooleanNumberString

    这 5 种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。

  • 引用数据类型:ObjecArrayDateRegExpFunction

    引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript 不允许直接访问内存中的位置,

    也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。

    为此,引用类型的值是按引用访问的(当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性时,操作的是实际的对象)

按照上面红宝书中所描述的不同处,所以变量的复制也会有所不同,基本数据类型复制的时候会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上;对于引用类型则是复制其指针,该指针指向存储在堆中的一个对象

image-20200901234801250

这也就引出了深拷贝与浅拷贝的问题,这边不做展开了。

按照上面的描述,来思考一个问题,函数传参数若入参是引用类型,那么这个时候函数内部对参数做了一些修改,是否会影响原来由的参数

function setName(obj) { 
  obj.name = "Nicholas";
} 
var person = new Object(); 
setName(person); 
alert(person.name); //"Nicholas"```

看起来好像会影响。但是实际并非如此,函数传参是值传递,就像基本数据类型那样

function setName(obj) { 
 obj.name = "Nicholas"; 
 obj = new Object(); 
 obj.name = "Greg"; 
} 
var person = new Object(); 
setName(person); 
alert(person.name); //"Nicholas"

​ 这个例子就可以说明即便传入值是引用类型,也是值传递。可以把 ECMAScript 函数的参数想象成局部变量,用完即销毁。

顺便提一句变量类型检测typeof用于检测基本数据类型对于引用数据类型只会返回'object',这是可以用instanceof去检测是具体是那种引用类型(根据它的原型链来识别)

alert(person instanceof Object); // 变量 person 是 Object 吗?
alert(colors instanceof Array); // 变量 colors 是 Array 吗?
alert(pattern instanceof RegExp); // 变量 pattern 是 RegExp 吗?

JS的作用域

​ JS分为全局作用域跟局部作用域(函数作用域),当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。当在某个环境中为了读取或写入而引用一个标识符时,会从当前作用域前段的优先查找,如果没有找到就往上一级作用域查找。

在es6之前申明变量都是使用var,var并没有块级作用域,只有局部作用域,会有变量提升,未申明使用,不会报错且值为undefined; letconst具有块级作用域,ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

JS的垃圾回收机制

​ JavaScript 是一门具有自动垃圾收集机制的编程语言,开发人员不必关心内存分配和回收问题。对于一个变量是否可以回收的判定依据是该变量是否被引用,也就是可达性。可以对 JavaScript 的垃圾收集例程作如下总结。

1.离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除。

2.“标记清除”是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然 后再回收其内存。

3.另一种垃圾收集算法是“引用计数”,这种算法的思想是跟踪记录所有值被引用的次数。JavaScript引擎目前都不再使用这种算法;但在 IE 中访问非原生 JavaScript 对象(如 DOM 元素)时,这种算法仍然可能会导致问题。

4.当代码中存在循环引用现象时,“引用计数”算法就会导致问题。

5.解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用。

参考文献:前端面试:谈谈 JS 垃圾回收机制