为了账号安全,请及时绑定邮箱和手机立即绑定

闭包相关的问题

闭包相关的问题

小唯快跑啊 2019-02-15 19:15:15
var arr = [ { name: '张三1'},            { name: '张三2' },            { name: '张三3' },            { name: '张三4' } ];for ( var i = 0; i < arr.length; i++) {     arr[ i ].sayHello = function () {         console.log(i);      };}arr[0].sayHello(); // 4arr[1].sayHello(); //4var arr = [ { name: '张三1'},    { name: '张三2' },    { name: '张三3' },    { name: '张三4' } ];for ( var i = 0; i < arr.length; i++) {    // arr[ i ] 绑定方法    arr[ i ].sayHello = function () {        // 打印名字        console.log(i);    };}for ( var i = 0; i < arr.length; i++ ) {    arr[ i ].sayHello(); // 0, 1, 2, 3}为什么两次执行结果不一样呢
查看完整描述

1 回答

?
繁花如伊

TA贡献2012条经验 获得超12个赞

我试着把问题分析得详细一点,通过举例子的方式把问题讲清楚:


首先这个问题如三楼所说,不涉及闭包,主要涉及的是作用域问题,下面一步一步来看


例1:


console.log(i); // undefined

console.log(j); // undefined


for (var i = 0; i < 4; i++) {

    var j = 100;

}


console.log(i); // 4

console.log(j); // 100

先看例1,第一次打印i与j都是undefined(因为没有定义),而第二次却有值了,这是因为在for循环内没有自己的作用域(在es5中只有function有自己的作用域),即是说在for内部定义的变量的作用域不仅限于for内部,外部照样能访问。


例2:


var x;

console.log(x); // undefined


var y = 200;

var y;

console.log(y); // 200

看例2,

变量x使用var声明,但没有被赋值,所以结果为undefined;

变量y使用var声明并赋值,所以这时候y的值为200,

再使用var重新声明一次,这时候原来的变量y应该是被清除掉了,并重新定义一个新的y,因为没有被赋值,所以此时y应该是undefined,但结果却是200


这说明在同个作用域内,使用var多次声明同一个变量名,并不会把原有变量从内存中移除并重新分配内存,而是继续使用原有的内存地址,即是说在同个作用域内,同一个变量名只能被var声明一次,后面的var不起作用。


明白了上面两点后,再来看题主的第一段代码


var arr = [ { name: '张三1'},

            { name: '张三2' },

            { name: '张三3' },

            { name: '张三4' } ];

for ( var i = 0; i < arr.length; i++) {

     arr[ i ].sayHello = function () {

         console.log(i);

      };

}

arr[0].sayHello(); // 4

arr[1].sayHello(); //4

这段代码只有一个作用域(因为for没有自己的作用域呀),所以在for内部声明的i也属于这个作用域,并且整段代码下来只有一个名为i的变量,所以console.log(i)这里打印的始终是同一个变量i,for循环后i变为4,所以打印结果始终是4


再看题主的第二段代码


var arr = [ { name: '张三1'},

    { name: '张三2' },

    { name: '张三3' },

    { name: '张三4' } ];

for ( var i = 0; i < arr.length; i++) {

    // arr[ i ] 绑定方法

    arr[ i ].sayHello = function () {

        // 打印名字

        console.log(i);

    };

}

for ( var i = 0; i < arr.length; i++ ) {

    arr[ i ].sayHello(); // 0, 1, 2, 3

}

这段代码也是只有一个作用域,同样整段代码也是只有一个名为i的变量,不同的是在第二个for循环里,每次循环都改变了这个变量i的值,改变之后再打印这个i,当然结果就是改变后的值了,即0, 1, 2, 3了


查看完整回答
反对 回复 2019-02-19
  • 1 回答
  • 0 关注
  • 394 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信