JavaScript 编程:3.变量、作用域和内存

JavaScript 变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已。

基本类型和引用类型

ECMAScript 变量的两种数据类型:

数据类型 基本类型 引用类型
含义 简单的数据段,5种基本数据类型:UndefinedNullBooleanNumberString 由多个值构成的对象。
访问方式 按值访问,可以操作保存在变量中的实际的值。 按引用访问,不能直接操作对象的内存空间。
保存区域 栈内存 堆内存
复制 开辟新的内存空间 两个指针引用同一个对象

动态的属性

可以为引用类型添加、改变、删除属性和方法:

var person = new Object();
person.name = "Nicholas";
console.log(person.name);    // Nicholas

不能给基本类型的值添加属性:

var name = "Nicholas";
name.age = 27;
console.log(name.age);    // undefined

复制变量值

  • 基本类型:会开辟新的内存,两个值互不影响。
  • 引用类型:指针,指向存储在堆中的同一个对象。

从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

从一个变量向另一个变量复制引用类型的值,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。

传递参数

ECMAScript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样。

在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用 ECMAScript 的概念来说,就是 arguments 对象中的一个元素)。

在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。

// 基本类型传递参数
function addTen(num){
  num += 10;
  return num;
}

var count = 20;
var result = addTen(count);
console.log(count); // 20,原来的基本数据类型值没有变化。
console.log(result); // 30

// 引用类型传递参数
function setName(obj) {
    obj.name = "Nicholas";
}

var person = new Object();
setName(person);
alert(person.name);    //"Nicholas",原来的对象属性也跟着改变了

检测类型

  • typeof 操作符是确定一个变量是字符串、数值、布尔值,还是 undefined 的最佳工具(检测基本类型)。
  • instanceof 操作符用于确定一个值是哪种引用类型。如果变量是给定引用类型(根据它的原型链来识别)的实例,instanceof 操作符返回 true
  • 因为所有引用类型的值都是 Object 的实例。因此,在检测一个引用类型值和 Object 构造函数时,instanceof 操作符始终会返回 true
  • 使用 instanceof 操作符检测基本类型的值,则该操作符始终会返回 false,因为基本类型不是对象。

💡 确定一个值是哪种基本类型可以使用 typeof 操作符,而确定一个值是哪种引用类型可以使用 instanceof 操作符。

let person = new Object();
console.log(person instanceof Object); // true
console.log(person instanceof Array); // false

let colors = ['blue', 'green', 'yellow'];
console.log(colors instanceof Array); // true

执行环境及作用域

  • 全局执行环境;
  • 函数执行环境;
  • 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
  • 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。
  • 作用域链的用途:保证对「执行环境有权访问的所有变量和函数」的有序访问。
执行环境及作用域

查询标识符的搜寻过程:从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。有则返回,无则继续沿作用域链向上搜索。

延长作用域链

有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。

当执行流进入下列任何一个语句时,作用域链就会得到加长:

  • try-catch 语句的 catch 块;
  • with 语句。

没有块级作用域 & 作用域链

在 JavaScript 中,if 语句中使用 var 声明的变量会将变量添加到当前的执行环境中:

if(true) {
    var color = "blue"; // 变量会被添加到当前执行环境(这里是全局环境)。
} // if语句结束后,变量不会被销毁。

// if{} 外部依然可以访问到内部声明的变量
alert(color); // "blue"

for 语句:

// 使用 var 关键字声明的变量没有块级作用域
for (var i = 0; i < 10; i++) {
  console.log(i);
}
console.log(i); // 10

// 使用 let 关键字声明的变量有块级作用域
for (let i = 0; i < 10; i++) {
  console.log(i);
}
console.log(i); // ReferenceError: i is not defined

💡 ES6 中的 letconst 添加了块级作用域的特性。

垃圾收集

JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。

原理:找出不再继续使用的变量,释放其占用的内存。垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行垃圾收集和释放操作。

JavaScript 的两种垃圾收集策略:

  1. 标记清除(主流方法):进入环境-离开环境;给当前不使用的值加上标记,然后再回收其内存。
  2. 引用记数(不再使用);存在循环引用问题。

管理内存

JavaScript 在进行内存管理及垃圾收集时面临的最主要的一个问题:分配给 Web 浏览器的可用内存数量通常要比分配给桌面应用程序的少。

因此,确保占用最少的内存可以让页面获得更好的性能。

解除引用:为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用。

解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。

手工解除引用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容