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里的值都不一样(不知道是否正确)} 最终导致结果是这样的。

0 0
原创粉丝点击