为什么函数赋值为null后,后续还会执行?
<button id="btn">btn</button>
function log () {
console.log('111')
}
let btn = document.querySelector('#btn')
btn.addEventListener('click', log)
btn.addEventListener('click', function () {
console.log(log)
log = null
console.log(log)
})
第一次点击输出:
111
log函数
null
后续点击输出:
111
null
null
问题?
为什么log函数赋值为null后,后续点击还会执行?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
换个写法就另当别论了:
看起来好比某人被骗进黑煤窑了,家里人找不到他,就申请把他户口注销了,但注销并不影响他继续挖煤。
log是一个变量,他的值是内存中的函数fn,addEventListener绑定了一个事件,回调函数为log,其实是内存中的函数fn,现在把log变为null,但是内存中的函数fn还是存在的,因为事件回调还在引用他,函数回调也能通过这种形式解绑,需要使用removeEventListener
函数名是指针。
感觉和这个例子是相仿的,即使obj = null,但是里面的定时器依然会触发
这个其实是你理解上有些偏差,注意
中,你的btn按钮的
click
事件处理先是被添加了一开始log
函数(所指的处理过程),后又添加了个匿名函数处理过程,所以实质上其对应的处理过程为在第一次运行时,log开始是log函数定义,后面变成了null。
你想取消btn的处理,其实应该是采用
btn
的removeEventListener
来移除,注意,removeEventListener
只能移除外部有名函数处理,匿名的不能简单移除。举个例子
你的手上涂满了红色的染料,我碰了一下你的手,我也粘上了红色染料,你将手上的红色染料洗掉了,那我手上的红色染料就会消失么,显然不会。
addEventListener是将log的值绑定到了click函数上,并不是将log绑定上了。就好比我手上的红色是染料,而不是我的手换成了你的手。
因为java只有一种传递参数的方式:值传递。
在值传递中,实参的值被传给形参,方法体内对形参的任何赋值操作都不会影响到实参。
这个其实就是个值传递和引用传递的问题,前面两个哥们说得很有意思,但是我觉得都没说到点子上。
JS 中基本数据类型
基本的数据类型有:
undefined,boolean,number,string,null
。 基本类型存放在栈区,访问是按值访问的,就是说你可以操作保存在变量中的实际的值。也就是说,这种赋值类似于拷贝了一份。a和b在
var b = a;
后就再也没有关系了。互不影响。引用赋值
引用类型指的是对象:js中的
array
和object
。可以拥有属性和方法,并且我们可以修改其属性和方法。引用对象存放的方式是:在栈中存放变量名(该变量的值是堆中真实数据的指针(对象在堆中的存放地址)),在堆中存放数据(真正的数据)。对象使用的是引用赋值。当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在堆中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
JS 函数是值传递
JS是值传递,那么传递引用类型和基础类型都是值传递,都是拷贝一份,但是引用类型变量实际上存的是对象/数组的指针,所以对于引用类型的传递,函数调用时候产生的实参是相当于变量的指针拷贝。另外对于函数来说,定义函数的时候,函数名实际存放的是具体函数的一个指针,参考上面关于堆栈存储的说明。
用你这个例子来说明:
所以你看,产生上面的结果就很容易理解了吧?