javascript 中的声明作用域范围以及指针引用的问题。

看了很多的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 undefined
item2 undefined
item2 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 1
item2 2
item2 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 1
item1 2
item2 3

这又是什么原因呢?
这个还是作用域的问题,当在for循环中,每一次循环 i和item 都会被销毁,因为他们不是引用类型(如果是引用类型会怎么样呢,自己猜吧)所以每循环一次 function() { console.log(item + ’ ’ + list[i])} 里的值都会被固定,然后被销毁并在下一次从新赋值。{也可以理解为item和i没有被销毁,只是每次for循环都指向新的值,所以每次的item里的值都不一样(不知道是否正确)} 最终导致结果是这样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值