1. 程式人生 > 實用技巧 >js中和html中onclick繫結函式要不要加括號的問題

js中和html中onclick繫結函式要不要加括號的問題

很早之前看過這個問題,幾年了,再看到這樣的程式碼時都忘了。

起初引起疑惑的程式碼內容:

<!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);