3. Javascript学习笔记——变量、内存、作用域
3. 变量、内存、作用域
3.1 基本类型和引用类型的值
ECMAScript 变量可能包含两种不同数据类型的值:基本类型值【Undefined、Null、Boolean、Number 和 String。 这 5 种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值】和引用类型值【在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的】。基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
动态的属性:
对于引用类型的值,可以添加、更改、删除属性和方法;但是基本类型不可以这么做。
复制变量值:
当复制一个基本类型的值时,会创建一个新的变量副本。两个变量完全独立。
当复制一个引用类型的值时,复制的是一个引用。两个变量都引用一个对象。当改变原变量的值时,新复制的也会改变。
var a=[1,2,3]; var b=a; a[0]=0; alert(b); //0,2,3
传递参数:
当传递一个基本类型的值时,是按值传递,不能更改外部的值。
当传递一个引用类型的值时,是引用传递,可以更改外部的值。
检测类型:
typeof xxx变量 instanceof 类型 /pattern/i instanceof RegExp => true
3.2 执行环境和作用域
执行环境(execution context) 是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。
每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。虽然无法通过代码访问这个对象,但是解析器在处理数据时会在后台使用它。
全局执行环境是最外围的一个执行环境。根据 ECMAScript 实现所在的宿主环境不同(浏览器、Node.js),表示执行环境的对象也不一样。在 Web 浏览器中,全局执行环境被认为是 window 对象,因此所有全局变量和函数都是作为 window 对象的属性和方法创建的。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。
每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。ECMAScript 程序中的执行流正是由这个方便的机制控制着。
当代码在一个环境中执行时,会创建变量对象的一个作用域链(sope chain)。作用域链的用途是保证对有权访问的执行环境里的变量和函数的有序访问。作用域链的前端,是当前所执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activation object)作为变量对象。活动对象最开始只包含一个变量,即arguments对象(不再全局环境中存在)。作用域中的下级各变量对象来自包含(外层)环境,再下一个变量来自下一个包含环境。这样一直延伸到全局执行环境,全局执行换金过得变量对象始终都是作用域链的最后一个对象。
标识符的解析是沿着作用域链一级一级地搜索标识符的过程,搜索过程从作用域链的前端开始,然后逐级地向后回溯,知道找到标识符为止(找不到则发生错误)。
例如:
/// 下面这段代码中,changeColor()的作用域链中包含两个对象:他自己变量对象(其中定义着arguments对象) 和全局环境的变量对象。在函数内部可以访问变量color就是因为可以再这个作用域链中找到它。
var color = "blue";
function changeColor(){
if (color === "blue"){
color = "red";
} else {
color = "blue";
}
}
changeColor();
alert("Color is now " + color); //red
///以下代码共涉及 3 个执行环境:全局环境、changeColor()的局部环境和 swapColors()的局部环境。
// 2. 全局环境中有一个变量 color 和一个函数 changeColor()。
// 1. changeColor()的局部环境中有一个名为 anotherColor 的变量和一个名为 swapColors()的函数,但它也可以访问全局环境中的变量 color。
// 0. swapColors()的局部环境中有一个变量 tempColor,该变量只能在这个环境中访问到。无论全局环境还是 changeColor()的局部环境都无权访问 tempColor。然而,在 swapColors()内部则可以访问其他两个环境中的所有变量,因为那两个环境是它的父执行环境。
var color = "blue";
function changeColor(){
var anotherColor = "red";
function swapColors(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
// 这里可以访问 color、anotherColor 和 tempColor
}
// 这里可以访问 color 和 anotherColor,但不能访问 tempColor
swapColors();
}
// 这里只能访问 color
changeColor();内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境之间的联系是线性、有次序的。每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
函数参数也被当作变量来对待,因此其访问规则与执行环境中的其他变量相同。
延长作用域链:
//虽然执行环境的类型总共只有两种——全局和局部(函数),但还是有其他办法来延长作用域链。就是当执行流进入下列任何一个语句时,作用域链就会得到加长:
// try-catch 语句的 catch 块;
// with 语句。
//这两个语句都会在作用域链的前端添加一个变量对象。对 with 语句来说,会将指定的对象添加到作用域链中。
对 catch 语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。下面看一个例子。
function buildUrl() {
var qs = "?debug=true";
with(location){
var url = href + qs;
}
return url;
}
//with 语句接收的是 location 对象,因此其变量对象中就包含了 location 对象的所有属性和方法,而这个变量对象被添加到了作用域链的前端。
//buildUrl()函数中定义了一个变量 qs。当在with 语句中引用变量 href 时(实际引用的是 location.href),可以在当前执行环境的变量对象中找到。
当引用变量 qs 时,引用的则是在 buildUrl()中定义的那个变量,而该变量位于函数环境的变量对象中。至于 with 语句内部,则定义了一个名为 url 的变量,
因而 url 就成了函数执行环境的一部分,所以可以作为函数的值被返回。
没有块级作用域:
// 在if语句中定义了变量color,如果在C/C++、Java中,color会在if语句执行完毕后被销毁。但在JavaScript中,if语句中的变量声明会将变量加到当前执行环境中(这里是全局环境)。
if (true) {
var color = "blue";
}
alert(color); // "blue"
// 对于有块级作用域的语言来说,for 语句初始化变量的表达式所定义的变量,只会存在于循环的环境之中。而对于 JavaScript 来说,由 for 语句创建的变量 i 即使在 for 循环执行结束后,也依旧会存在于循环外部的执行环境中。
for(var i = 0; i < 10; i++){
doSomething();
}
alert(i); //
// 【变量声明】
// 如果使用 var 声明变量,则会被自动添加到最近的环境中。在函数内部,最接近的环境就是函数的局部环境。如果初始化变量时,没有使用var声明,则该变量会被自添加到全局环境中。
// 【查询标识符】
//当在某个环境中引用一个标识符时,必须通过搜索来确定该标识符实际代表什么。搜索过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。如果在局部环境中找到了该标识符,搜索过程停止,变量就绪。如果在局部环境中没有找到该变量名,则继续沿作用域链向上搜索。搜索过程将一直追溯到全局环境的变量对象。如果在全局环境中也没有找到这个标识符,则意味着该变量尚未声明
3.3 垃圾收集
3. Javascript学习笔记——变量、内存、作用域的更多相关文章
- javascript学习笔记 - 变量、作用域和内存问题
一 垃圾收集 javascript具有自动垃圾收集机制.由垃圾收集机制标找出不再使用的变量.按照固定间隔的时间进行销毁,释放内存. 1.找出不再使用的变量的方法,如下: 1-1.标记清除 垃圾回收器 ...
- php学习笔记-变量的作用域
这个东西很难理解,但很重要,我觉得非常容易出错. PHP中的变量按照作用域分为有两种,一种是global,一种是local. 函数内部声明的变量就叫local型变量,只能在函数内部被访问到.一句话,l ...
- JavaScript高级程序设计学习笔记--变量、作用域和内存问题
传递参数 function setName(obj){ obj.name="Nicholas"; obj=new object(); obj.name="Greg&quo ...
- JavaScript学习笔记——变量和数据类型
一.javascript命名规范 1. 严格区分大小写 2. 变量的命名必须以字母或 _或 $开头,余下的部分可以是任意的字母,数字,或者是 _或者是$ 3.不能用关键字或者是保留字命名. 4.jav ...
- R语言学习笔记-变量的作用域
R语言是如何将变量值和变量绑定的 在r语言中,当前的 workspace就是global enviroment,当输入变量名时,首先会在global enviroment中搜索该变量,如有,则将它显示 ...
- js学习之变量、作用域和内存问题
js学习之变量.作用域和内存问题 标签(空格分隔): javascript 变量 1.基本类型和引用类型: 基本类型值:Undefined, Null, Boolean, Number, String ...
- JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
JavaScript:学习笔记(7)——VAR.LET.CONST三种变量声明的区别 ES2015(ES6)带来了许多闪亮的新功能,自2017年以来,许多JavaScript开发人员已经熟悉并开始使用 ...
- JavaScript学习笔记(十一)——闭包
在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...
- Java程序猿JavaScript学习笔记(4——关闭/getter/setter)
计划和完成这个例子中,音符的顺序如下: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScr ...
随机推荐
- smarty 使用php函数
strtotime() time() <{if strtotime($activity.start_time) gt time()}> <a href="?action=d ...
- C#中把任意类型的泛型集合转换成SQLXML数据格式的小例子
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...
- BBS项目之后台管理
一:后台管理,添加文章样式编写 创建 一个后台管理模板前段页面 <!DOCTYPE html> <html lang="en"> <head> ...
- sklearn中的随机森林
阅读了Python的sklearn包中随机森林的代码实现,做了一些笔记. sklearn中的随机森林是基于RandomForestClassifier类实现的,它的原型是 class RandomFo ...
- JavaScript面向对象编程小游戏---贪吃蛇
1 面向对象编程思想在程序项目中有着非常明显的优势: 1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块 1- 2 维护非常方便并且成本较低. 2 这个demo是采用了 ...
- UVa 11090 Going in Cycle!! (Bellman_Ford)
题意:给定一个加权有向图,求平均权值最小的回路. 析:先十分答案,假设答案是 ans,那么有这么一个回路,w1+w2+w3+...+wk < k*ans,这样就是答案太大,然后移项可得,(w1- ...
- URAL 1430. Crime and Punishment(数论)
题目链接 题意 :给你a,b,n,让你找出两个数x,y,使得n-(a*x+b*y)最小. 思路 : 分大小做,然后枚举a的倍数 #include <stdio.h> #include &l ...
- Web大文件上传(断点续传)控件-Xproer.HttpUploader6-安装教程
安装教程: IE8控件安装教程 IE9控件安装教程 Firefox控件安装教程 Chrome控件安装教程 Chrome 45+控件安装教程 相关问题: 提示Runtime Error错误 360拦 ...
- Appium 简介及工作原理
申请:本文介绍主要是针对Android. 1.什么是Appium: Appium是一个开源.跨平台的测试框架,可以用来测试原生及混合的移动端应用.Appium支持IOS.Android及Firefox ...
- Shell脚本中$0、$?、$!、$$、$*、$#、$@
1. $$Shell本身的PID(ProcessID) 2. $!Shell最后运行的后台Process的PID 3. $?最后运行的命令的结束代码(返回值) 4. $-使用Set命令设定的Flag一 ...