JavaScript学习日志(一):变量,作用域和内存问题
一,变量分为两种类型:基本类型值和引用类型值,基本类型包括:Undefined, String, Boolean, Null, Number,我们无法给基本类型值添加属性;
犀牛书上给的定义是,数据类型分两类:原始类型和对象类型,原始类型包括Number,String,Boolean,还有两个原始值,Null和Undefined。
二,复制变量值的时候,如果改变复制的值,那么原来的值是否会变化?
这个取决于原来的值是什么类型:
1.基本类型值:只是存在于栈内存中,如果复制,相当于栈内存里又多了一个值,两者相互独立,改变其中一个,另一个不变
2.引用类型值:实际上是指向堆内存中的一个object,复制相当于多了一个指针,也是指向这个堆内存中的一小块object,改变其中一个,所指的这个object也发生改变(注意,这个object不是整个大的Object对象,而只是堆内存其中的一小个),那么所有指向该object的值全部发生变化。
三,传递参数的时候,如果参数在局部作用域下发生变化,那么参数会变化吗?
js中,所有的参数传递都是按值传递,不管是基本类型还是引用类型。不同的类型下不同的讨论方式:
1.基本类型值:将参数传递给函数执行,实际上就是复制了一个值,给了函数,即基本类型值的复制,局部作用域怎么变化,原值都不会变。
2.引用类型值:将引用类型值作为参数传递给函数,实际上相当于把这个值在内存中的地址作为一个值传递给了函数,那么此时在函数里改变这个复制的地址,原来的值一定会发生改变,因为两个值指向的是同一个地址,但是如果此时在函数内部再声明一个新的引用类型值,name一样,此时这个指向的object和刚刚那两个指向的就不一样了,再次修改这个值,原来的相同name的值不会发生改变了,因为它是按值传递的。改变函数内部的参数值,外部参数也会发生改变,看起来好像是按引用传递,实际上却不是,只是因为二者引用的是同一个object,因为类型是引用类型。
附上一堆代码:
function setName(obj){ obj.name="ABC"; obj=new Object(); obj.name="BCD"; } var person=new Object(); setName(person); alert(person.name);// ABC
四,执行环境以及作用域的问题:
执行环境定义了变量或函数有权访问的其他数据(这里的变量或函数可能是外部环境的,也可能是当前执行环境的)。每个执行环境有一个对应的变量对象,这里面存储了在该环境下定义的所有变量和函数(在犀牛书上定义的是当这个函数被调用的时候,它会创建一个新的对象来存储它的局部变量,这里我理解的这个创建的新的对象就是变量对象)。执行环境中所有的代码执行完毕后,当前环境就会销毁,全局执行环境直到应用程序退出时才会销毁。
每个函数都有自己的执行环境,执行流进入一个函数时,函数当前的执行环境被推入环境栈中,此时控制权就由原来的执行环境而移交给当前执行环境下,当函数执行完毕后,栈就会将这个环境推出,控制权也重新回到原来的执行环境下。每一个正在执行的环境都放在环境栈里面。ECMAScript的执行流就是这个机制。
在javascript最顶层的代码中(不包含任何函数定义内的代码),作用域链是由一个全局对象组成(也可以理解成全局环境下的变量对象),在不包含嵌套的函数体内,作用域链上有两个对象(变量对象),第一个是定义的函数参数和局部变量的对象(变量对象)。如果这个函数体内有嵌套,那么作用域链上至少有三个对象(变量对象)。当定义一个函数的时候,实际上保存了一个作用域链,当代码在一个环境中执行的时候,就会创建一个变量对象的作用域链,换句话说,当函数被执行的时候,刚刚创建的那个存储局部变量的对象(变量对象)就被添加至该函数在定义的时候保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的链,这里我再解释的通俗一点:定义函数的时候保存的那个作用域链只有短短的一截,因为此时函数还没有被调用,所以它不存在什么变量对象,也跟外部没有联系,所以这一截作用域链上面什么都没有,当调用函数的时候,作用域链就会与外界的作用域链相连接,变长,二截或三截或更多,调用的时候内部所有的局部变量都会重新定义一遍,所以就有了变量对象,此时作用域链就会绑上这个变量对象,所以这个作用域链相当于一个全新的作用域链,它更长了。我再结合执行流的机制再补充一点,执行流进入每一个不同的函数的时候,都相当于一次作用域链的拼接,每一个函数内部都有一小截,被调用的时候,就接上外部的执行环境的作用域链,调用完了就断开,换下一个接上,就是这么个过程,所以每次执行函数的时候,作用域链都是新的。这个作用域链的用途是保证对所有能够在当前执行环境下有权访问的变量或函数的有序访问。(换句话说,在当前执行环境下,有哪些变量或函数是可以访问的,我通过作用域链就可以查到,而且是有序的查找,所以我认为其实作用域链就是当前,变量对象的排序)。这个作用域链的前端,是当前执行环境的变量对象。如果这个执行环境是函数,则将其活动对象作为变量对象。活动对象起初只有一个变量,就是arguments对象(全局环境中没有的)。作用域链上,从前端开始往后,下一个变量对象就是当前执行环境外的环境下的变量对象,再下一个就是再外一层环境的变量对象,(这个环境一层层的,就是执行流依次经过的环境,只不过是倒过来,从前往后的,从里到外),一直到最外层的全局执行环境:全局执行环境的变量对象一定是作用域链的最后一个对象。
标识符的解析就是沿着作用域链从前往后找的。
作用域链本质上是一个指向变量对象的指针列表,他只引用但不实际包含变量对象。 ——节选自闭包一节。
这里补充几个延长作用域链的方法(就是把变量对象直接添加到作用域链的前端):
1,try-catch语句的catch块
2,with语句(不推荐使用,严格模式下是禁止的):用法如下
with (document.forms[0]) {
// 直接访问表单元素
name.value = "";
address.value = "";
email.value = "";
}
这种减少了大量的输入,不用为每个属性添加document.forms[0]前缀,等同于下面
var f = document.forms[0];
f.name.value = "";
f.address.value = "";
f.email.value = "";
但是要注意一点,如果with中的变量没有被定义,那么就会创建一个局部或全局变量,with就等于没有,比如:
with(o) x = 1
如果o里面有x属性,那么就会直接覆盖为1,如果没有x属性,那么就等同于在当前环境下执行:
x = 1;
就会创建一个新的局部或全局变量。
3,apply和call,这个详见apply、call那篇随笔
==========
2017-12-14,再次理解作用域链:
函数定义的时候,会创建一条作用域链,当函数调用的时候,会创建一个变量对象来存储它的局部变量,并将这个变量对象添加到定义时候创建的作用域链上,同时创建一条更长的,用来表示函数调用作用域的链条,这个链条不是函数定义时创建的作用域链,那一条是函数自己的,而这一条表示函数调用作用域的链条是对于整个体系而言,它上面有很多不同执行环境下定义的变量对象,每一次执行函数都会在这条大链子前面添加一个变量对象。
JavaScript学习日志(一):变量,作用域和内存问题的更多相关文章
- 第一百零六节,JavaScript变量作用域及内存
JavaScript变量作用域及内存 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只 ...
- javascript学习日志:前言
javascript学习日志系列的所有博客,主要理论依据是<javascript权威指南>(犀牛书第6版)以及<javascript高级程序设计第三版>(红色书),目前js行业 ...
- JavaScript解析顺序和变量作用域
JavaScript基础之变量作用域. 一. 1.全局变量:全局变量的意思就是,在代码的不论什么地方都能够訪问到.注意:未定义 直接赋值的变量拥有全局属性. 2.局部变量:局部变量的意思就是,变量的作 ...
- javascript学习中自己对作用域和作用域链理解
在javascript学习中作用域和作用域链还是相对难理解些,下面我关于javascript作用域和作用域链做一下详细介绍,给各位初学者答疑解惑. 首先我们介绍一下什么是作用域? 从字面上理解就是起 ...
- 原生 javascript 学习之 js变量
1.变量的命名 方法的命名(驼峰命名法) 全部小写 : 单词与单词之间全部下划线 (my_namespace) 大小写混合 : 第一个单词首字母小写其他单词首字母大写. 规则 首字符 英文字母或下划线 ...
- javaScript的闭包 js变量作用域
js的闭包 js的变量作用域: var a=90; //定义一个全局变量 function test(){ a=123; //使用外层的 a变量 } test(); document.write(&q ...
- python3学习笔记12(变量作用域)
变量作用域 参考http://www.runoob.com/python3/python3-function.html Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量 ...
- Python 3 学习笔记之——变量作用域、模块和包
1. 变量作用域 Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的.变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python 的作用域一共 ...
- perl学习之六:变量作用域
变量作用域 (一)包变量 $x = 1 这里,$x是个包变量.关于包变量,有2件重要的事情要了解: 1)假如没有其他申明,变量就是包变量:2)包变量总是全局的. 全局意味着包变量在每个程序里总可访问到 ...
随机推荐
- Python爬虫初学(二)—— 爬百度贴吧
Python爬虫初学(二)-- 爬百度贴吧 昨天初步接触了爬虫,实现了爬取网络段子并逐条阅读等功能,详见Python爬虫初学(一). 今天准备对百度贴吧下手了,嘿嘿.依然是跟着这个博客学习的,这次仿照 ...
- python教程6-4:算数
参照练习2-9和练习5-3.将测试得分放到一个列表中,并且可以计算出平均分. python35 SuanShu_6_4.py SuanShu_6_4.py #coding=utf-8 def ave( ...
- offsetWidth\offsetleft 等图文解释
网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offs ...
- python 分支语句 循环语句
分支语句 #if-else if a > b: print('aaa') else: print('bbb') #if-elif-else if a > b: print('a>b' ...
- python--DenyHttp项目(1)--调用cmd控制台命令os.system()
os.system() 参数传递cmd命令,命令执行成功返回0,失败返回1 在网上查看使用ping命令,能否Ping通 大神们有 用正则的,有用Popen() os.system()直接用返回值,简单 ...
- How to remotely shut down any PC on same network
Syntax: net viewping (name of victim's PC)shutdown -i Empirical: Try one of the school's public PC R ...
- 605. Can Place Flowers种花问题【leetcode】
Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, ...
- "=="和equals方法究竟有什么区别?
(单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚) ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同, ...
- CgLib动态代理学习【Spring AOP基础之一】
如果不了解JDK中proxy动态代理机制的可以先查看上篇文章的内容:Java动态代理学习[Spring AOP基础之一] 由于Java动态代理Proxy.newProxyInstance()的时候会发 ...
- 马的遍历 洛谷 p1443
题目描述 有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步 输入输出格式 输入格式: 一行四个数据,棋盘的大小和马的坐标 输出 ...