javascript 中的声明作用域范围以及指针引用的问题。
来源:互联网 发布:手机exe解压软件 编辑:程序博客网 时间:2024/05/15 08:33
看了很多的javascript 感触良多,javascript的语法与c语言 c++完全不同。javascript的类(es6)也只是function的另一个表示法(语法糖)。本质上javascript的类就是function。
本文章主要是记录一下如何理解作用域。
如果想详细了解请参照How do JavaScript closures work
我只是把其中文章中没有列举的一下问题简要提一下
作用于中用var声明
别的不多说 该文章中的例子
function buildList(list) { var result = []; for (let i = 0; i < list.length; i++) { let item = 'item' + i; result.push( function() { console.log(item + ' ' + list[i])} ); } return result;}function testList() { var array=[1,2,3] var fnlist = buildList(array); // Using j only to help prevent confusion -- could use i. for (var j = 0; j < fnlist.length; j++) { fnlist[j](); }} testList() //logs "item2 undefined" 3 times
结果为
item2 undefineditem2 undefineditem2 undefined
为什么会这样,原因在于testList()运行的时候产生了一个testlist作用域,在这个作用域中有两个本地变量array 和运行buildList(array)。而buildList(array)运行的同时也会产生一个buildList作用域,本来运行buildList之后如果没有外部引用存在的话,垃圾回收机制会回收这部分内存空间。但是我们发现buildlist返回result是
[ function() { console.log(item + ' ' + list[i])} , function() { console.log(item + ' ' + list[i])} , function() { console.log(item + ' ' + list[i])} ,]
其中的item 和list[i]均引用了buldList的作用域变量。所以垃圾回收机制不会销毁它。而是保留他。直到作用于消失。
在buildList中声明了的
var result=[]var i //虽然声明在for里但它是属于buildLIST作用域的var item //虽然声明在for里但它是属于buildLIST作用域的
当程序运行的时候for循环了三次
var result = []; for (var i = 0; i < list.length; i++) { var item = 'item' + i; result.push( function() { console.log(item + ' ' + list[i])} ); } return result;
每一次循环就会i都会加1 item都会重新赋值 三次循环后i=3,item=“item2”(因为i++的值为3的时候i < list.length为假,不会再循环了);
所以所有的result里的function里 i定位到了3 item 定位到了“item2”,result返回后任然引用了buildList作用于
var result=[function() { console.log(item + ' ' + list[i])}, function() { console.log(item + ' ' + list[i])}, function() { console.log(item + ' ' + list[i])}]var i=3 //虽然声明在for里但它是属于buildLIST作用域的var item="item2" //虽然声明在for里但它是属于buildLIST作用域的
现在返回到testList作用域当中。现在的fnlist就等于
[function() { console.log(item + ' ' + list[i])},function() { console.log(item + ' ' + list[i])},function() { console.log(item + ' ' + list[i])}]
并且并且item ,i 指向buildLIST的作用域
下一步 for (var j = 0; j < fnlist.length; j++) { fnlistj; }执行 fnlistj,就会执行function() { console.log(item + ’ ’ + list[i])} 并且均指向了buildLIST作用域的值。
分析还没有结束 接着看
作用于中用let 声明
let声明与var不同,var的作用于不会局限在for循环语句和{ }里但是let会局限,也就是let在for循环,在{ }里存在的话在他们外面是访问不到的,这就会让上面的例子有所不同
把i用let来定义
function buildList(list) { var result = []; for (let i = 0; i < list.length; i++) { var item = 'item' + i; result.push( function() { console.log(item + ' ' + list[i])} ); } return result;}function testList() { var array=[1,2,3] var fnlist = buildList(array); // Using j only to help prevent confusion -- could use i. for (var j = 0; j < fnlist.length; j++) { fnlist[j](); }} testList() //logs "item2 undefined" 3 times
返回值为
item2 1item2 2item2 3
把 item 和 i 用let 定义
function buildList(list) { let result = []; for (let i = 0; i < list.length; i++) { var item = 'item' + i; result.push( function() { console.log(item + ' ' + list[i])} ); } return result;}function testList() { var array=[1,2,3] var fnlist = buildList(array); // Using j only to help prevent confusion -- could use i. for (var j = 0; j < fnlist.length; j++) { fnlist[j](); }} testList() //logs "item2 undefined" 3 times
结果为
item0 1item1 2item2 3
这又是什么原因呢?
这个还是作用域的问题,当在for循环中,每一次循环 i和item 都会被销毁,因为他们不是引用类型(如果是引用类型会怎么样呢,自己猜吧)所以每循环一次 function() { console.log(item + ’ ’ + list[i])} 里的值都会被固定,然后被销毁并在下一次从新赋值。{也可以理解为item和i没有被销毁,只是每次for循环都指向新的值,所以每次的item里的值都不一样(不知道是否正确)} 最终导致结果是这样的。
- javascript 中的声明作用域范围以及指针引用的问题。
- php foreach行声明变量的作用范围问题
- js变量声明以及作用域的问题
- JavaScript中的作用域与变量声明
- javascript中的ajax的作用域问题
- 变量的作用域的范围问题
- javaScript变量的作用范围
- javascript 变量的作用范围
- JavaScript中的作用域问题
- JavaScript中setTimeout的作用域以及this指向问题
- 这个关于c中break的跳转位置以及声明变量的作用域的问题。
- 线性链表中形参中的指针引用的问题
- JavaScript中的作用域以及this变量
- JavaScript中的作用域以及this变量
- 翻译 - JavaScript中的作用域与变量声明提升
- Shell编程中变量的声明、引用及作用域
- [JavaScript]使用块级作用域声明对象时要注意的一个问题
- JS中的作用域以及全局变量的问题
- android studio 安装assets目录下的apk包出现解析错误的问题
- 一,openstack 命令行管理(br-ex网络设定)
- #if 和#ifdef的区别
- 数据库SQL优化——学会使用PLSQL的执行计划
- Google/glog
- javascript 中的声明作用域范围以及指针引用的问题。
- 如何编译SQLite-How To Compile SQLite
- Java processor 阻塞
- Go 语言的垃圾回收算法被吹过头?与Java比如何?
- 块级元素与内联元素(行内元素)及浮动知识总结
- git 常规使用
- STL源码剖析在VS2010下运行出错
- Android studio————Gradle可能引起的文件
- 阅读ASCII