很早之前看过这个问题,几年了,再看到这样的代码时都忘了。
起初引起疑惑的代码内容:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script>
let json={
a: 12, b: 5,
show: ()=>{
console.log(this);
//alert(this.a+this.b);
}
};
json.show();
document.onclick=json.show; //注意这里直接赋值的是一个函数,而不是直接调用
</script>
</head>
<body>
</body>
</html>
=========我是分割线========
后来上网搜原因,下面为网络上的文章:
1、在js中绑定onclick事件为什么不加括号,在html代码中必须要加?
原文链接:https://www.cnblogs.com/qq254980080/p/10479295.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button id="btn">按钮</button>
</div>
<script>
var btn = document.getElementById("btn");
btn.onclick = demo();
//btn.onclick = demo;
/*加上括号是执行的意思,添加事件的回调函数应该就是给相应的事件属性赋值,
而很明显需要把一个函数赋值给这个事件属性,而不是函数的调用结果。
所以在js中的绑定是直接赋值。而在标签内的事件属性的值是由引号包裹的,
代表的是当点击该元素时,执行引号内的代码,直接把引号内的代码拿出来跑,
如果你不加括号,那就不会调用那个函数。*/
/*简单来说就是带括号的是执行一次函数,不带括号的函数就是一个函数对象*/
/*那下面这种意思就明显了,下面的这一句语句是将一个函数对象赋值给了btn.onclick
*/
// btn.onclick = function(){alert("DOM0级事件处理111");}
function demo(){
alert("111");
}
</script>
</body>
</html>
2、js中和html中onclick绑定函数要不要加括号的问题
原文链接:https://blog.csdn.net/qq_44606064/article/details/109017001
先说两者的区别在哪里
1.函数名其实就是指向函数体的指针
2.不加括号, 可以认为是查看该函数的完整信息,
3.不加括号传参,相当于传入函数整体
4.加括号 表示立即调用(执行)这个函数里面的代码(花括号部分的代码)
看下面代码就很好理解了:
<body>
<!--在html标签中是作为属性添加进去的,所以必须加括号,理解不了没关系,先看下面
对比一下就懂了-->
<button onclick="onclick1()">btn1</button>
<button id="btn">btn2</button>
</body>
<script>
function onclick1() {
alert("这是btn1的弹窗")
}
function onclick2() {
alert("这是btn2的弹窗")
}
//这个代码是正确的,在给btn2进行绑定事件的时候传入一个函数地址,当触发事件执行函数体,而不是进行事件绑定的时候执行函数
document.getElementById("btn").addEventListener("click",onclick2)
//下面代码错误的
//如果换成下面代码,就会在页面渲染的的时候执行弹窗,因为传入的是立即执行函数的结果
//document.getElementById("btn").addEventListener("click",onclick2())
</script>
3、JS中关于事件处理函数名后面是否带括号的问题
原文链接:https://www.jb51.net/article/97458.htm
今天总结一个关于事件处理程序的小细节。首先回顾一下事件处理的一些概念。
JS中的事件处理(事件绑定)就是让某种或某些事件触发某些活动。有两种常见的形式,分别是DOM Level 0 和DOM Level 2。这两种方式最大的区别就在于DOM 0级事件处理只能用于事件冒泡,而DOM 2级事件处理却可以通过设置第三个参数来分别支持事件冒泡和事件捕获。
DOM 0级事件处理一般是直接把一个函数分配给一个事件处理程序,既可以在元素中直接分配一个事件处理程序,如方式一所示;也可以在脚本中把函数分配给事件处理程序,如方式二所示。
<!--方式一-->
<div onclick="fun1();fun2(‘world!‘);"></div>
<!--方式二-->
<div id="a">点我</div>
<script>
var a=document.getElementById("a");
a.onclick=fun1; //方式二
function fun1(){
alert("hello!");
}
function fun2(cc){
alert(cc);
}
</script>
这两种方式的区别在上述示例中也显示了,第一种方式可以同时绑定多个处理函数,但要注意必须是全局函数,否则会抛出Reference错误。第二种方式只能一次绑定一个处理函数,否则新的函数会覆盖旧的函数。
DOM 2级事件处理不会直接绑定处理函数,而是将函数添加为一个事件监听器如下,他也可以绑定多个处理函数,不会产生覆盖。但这种方式存在浏览器兼容的问题,IE下必须用attachEvent方法代替。
a.addEventListener("click",fun1,false); //事件冒泡
a.addEventListener("click",anotherFun,false); //不会覆盖上一事件,均被执行
简单回顾到这里,言归正传,不知道在回顾的过程中大家有没有注意到一个令人困惑的小细节,就是引用函数的时候,函数名称后面有的时候加括号,有的时候不加括号。这到底对程序的运行有怎样的影响呢?我经过查阅资料按照自己的理解小小的总结如下。
首先是加括号的,你可能经常在程序里面这样写“fun1();”,没错,函数名后边加括号表示立即执行该函数,如果函数内存在返回值则得到该值。这样用的多了,你可能就习惯在所有调用函数的地方这样写,比如之前说的事件处理函数。但是,如果你这样做了那就可能造成一些失控的状况。比如说,你明明只是想在点击某一元素的时候才执行函数,却发现这个函数在一开始就被执行了。你可以发现,上面举例时所用的DOM0方式二和DOM2级事件处理函数都没有在函数名后面加括号,原因就在于避免这种状况发生。如果你加了括号,这个函数fun1就会被立即触发执行。
那为什么DOM0方式一中却有括号呢?那是因为标签的事件属性里引号之间会被当做js语句直接执行,加了括号才能保证调用并执行函数。但是由于是用元素标签这种方式绑定的事件,执行的时机就被控制在了点击该标签时触发。
如果没有函数名又想立即执行呢?也就是立即执行匿名函数表达式,这种模式很常见,来观察一下它的屁股后面是不是也跟着个立即执行小括号呢?注意,这种IIFE形式中包裹着整个函数体的小括号会限制作用域。具体对IIFE感兴趣的童鞋可以去查阅相关资料,这里不作赘述。
(function(){
//do something...
})();
现在再来分析不加括号的,前面我们提到了不加括号可以避免失控。是因为只将函数名传递给事件,相当于将函数指针(也就是这个函数的入口地址)传给元素事件。这样做的好处就在于可以在需要的时候找到函数并执行。打个小比喻来说,你和你的朋友会面,加了小括号时你的朋友就立即出现在你面前,他才不管你当时是不是在忙,有种不请自来的不快感;而不加括号相当于你的朋友告诉了你他家在哪,当你需要他的时候就来找他,这可真是位贴心的朋友啦。所以,大多数事件绑定都仅仅只是传递给事件一个函数指针也就是函数名。
这时又有一个问题,之前说明的都是无参函数,如果是像代码示例中的fun2这种有参函数怎么办呢?难道只能用DOM0的方式一那种方法么?当然是否定的,尽量不要使用DOM0方式一那种形式,不符合结构与行为分离的原则。一般这种情况下就是使用匿名函数解决了,如下代码所示。如果大家有什么好的建议也可以留言分享一下~
//DOM Level 0
a.onclick=function(){
fun2("world!");
};
//DOM Level 2
a.addEventListener("click",function(){fun2("world!");},false);