在做js二级下拉菜单,搞不懂 this 值引用和 for循环里索引值是咋回事

1.index是属性,实际上属性就是某个对象的专属变量。不知道你听过命名空间这个概念没有:实践中为了降低项目中出现变量名称冲突的概率,我们会在JS全局环境中只声明一个全局变量,然后在这个变量下面添加和命名相应的属性来保存你想保存的值。这种方式的好处就是不用使用var关键字来声明变量,只用在需要的时候直接在全局变量后面添加一个新的属性就行了。2.这个问题中,事件处理函数是注册在child上面的,等你在将来触发这个事件的时候就相当于执行了child.handlerfunction(),因此this在此时指代的是child,因此this.index也就是child.index,也就对应逆循环的时候保存的那个时刻的i值。3.同第二个问题,这里的this在触发函数事件的时候也是指的child。如果你真的在看JS语言精粹,你可以去看第28页方法调用模式,里面提到:一个函数在作为某个对象的方法被调用时,this才会被绑定到调用该方法的对象。从这里作者提出this的绑定具有延迟性,我个人理解的是,与其说是延迟性,不如说是即时性。this不是一个常规的对象,你可以把它看成是一个即时的指针,可能上一秒在函数A中指代某个对象,下一秒又会跑到函数B中指代另一个对象,从而保证了this的高度复用。这也是JS引入this的初衷,它给与了JS强大而灵活的引用特性。4.这个问题我之前回答过,传送门稍后。我仍然要说的就是,写程序的时候一定要分清代码层级,也就是要清楚哪一层代码在当前只是被定义,哪一层代码是正在被执行。你的例子中,window.onload在页面载入时就会被执行,因此函数内的第一层代码会被执行,oUl 中的 i 就是第一层被执行的代码,此时的 i 会被替换为每次迭代中 i 的实际值。你说的 i 为定值的情况也是存在的,如果你在oUl中的事件处理函数内直接书写 i ,那么在将来触发事件函数的时候 i 就是循环结束后的值+1,因为在执行window.onload的时候oUl的事件处理函数中的 i 只是一个字面符号,并未被执行,也就不会被替换为每次迭代时 i 的实际值。更具体原因参见这个回答:js关于for循环中的闭包问题? - 闭家锁的回答
■网友
同新手,说一下最后一个注释的疑问i为什么不是4,这是作用域问题,这个i实在循环内部,他的i是可以循环1 2 3 4的,因为i和调用的函数在同一个作用域。同样你在这个函数内部再引用一次i就是4,因为那一次调用的函数本身没i,就去父级寻找,这时候父级i已经循环完毕就是4。如果想在内部函数也获取到i,可以用自执行函数(function(e){ alert(e)})(i) 这样可以获取到你当前的i。手机打的比较乱。 倒数第二个问题。这个this和上面是不是一样,我觉得如果抛开例子来讲他们是不一样的。var that =this 这个地方楼下已经说了,方便调用,这里把this存储进去,(当把一个东西存入变量,这代表的是存入时候的值,这个函数存入的this,无论在哪调用,他都代表这个函数的this,而不是调用的函数的this)这样他里面的子函数再需要调用的时候可以直接去调用that,就等于调用了当前的这个this,如果直接this,那调用的肯定是子函数里的,无法向上查找父函数的this。新手说的有不对的地方,恳请各位大大指点。另吐槽一下手机版修改个错别字真不容易。
■网友
谢邀。1. child只是一个javascript object而已,dom api里option对应的object是没有index的。此处其实是我们人为给这个object赋一个index,方便触发下面的事件时知道是哪个(第几个)option。从实际进行的操作来看,这里跟var a = {};a.index = 1;没有本质区别。2.此处的index就是1中设置的index。设置index帮助我们分清不同的option。3. javascript的scope(约等于命名空间,储存变量的地方)是跟function在一起的,this亦然。所以显然两个this不一样,事实上var that = this;function inner() { that.whateverPropertyThatExists; //本function内没有that,但上级有,可以读到,而且值就是上一个函数的this this.whateverPropertyThatExists; //假如这个function绑定的this没有这个属性,就是undefined;此处的this只跟 inner 这个function有关


推荐阅读