顯示廣告
隱藏 ✕
※ 本文為 dinos.bbs. 轉寄自 ptt.cc 更新時間: 2012-07-14 07:12:03
看板 Ajax
作者 mrbigmouth (拒絕崩潰的蒲公英)
標題 Re: [問題] (...)()或(...)(window)是什麼意思?
時間 Sat Jul 14 00:56:33 2012


※ 引述《cyutdt (DT)》之銘言:
: 常在程式看到
: (function() {
:     ...
: })();
: 或
: (function() {
:     ...
: })(window);
: 我已經看過closure的相關教學和討論
: 還是不曉得這跟closure是否有關聯
: 還是跟$(document).ready(function(){});有什麼關係呢?
: 看到一些這種範例
: 不曉得為什麼要這樣寫

雖然我覺得google一定找得到答案
但現在剛好無聊就來說一說我的理解好了
如有錯誤煩請指證

(function() {})()
上面這種格式
就是所謂的self invoking anonymous function
     自我 執行   匿名   函數
在程式邏輯上是"製造一個匿名的函數並且立刻執行"
其目的主要在於產生一個私有的scope,使在其內宣告的變數不會與外界混淆

以我最常使用的格式為例,會在寫一些獨立運行的網頁程式的一開始寫出如下的宣告

(function(window) {
    var document = window.document,
        $ = window.jQuery,
        variableA,
        variableB,
        variableC,
        .
        .
        .
        variableN;

    //下面才開始寫程式

    //寫到這裡結束程式

    //如果有必要,將需要輸出的函式/功能指派到window下的廣域變數
    window.OOXX = variable???;
})(window);

這樣做最主要的好處在於,
在這個裡面所宣告的變數絕對不會被外界的變數干擾(因為指不到),
不管該網頁引入了多少library、後來者又亂插入了多少script、
server或使用者瀏覽器亂安裝的plugin在網頁後方又加了什麼奇怪的壞掉script....
我寫在這個scope裡的區域變數都絕對不可能會被影響到,
也因此保證了我寫出的這個獨立運作的程式在自己運作時絕對不會有問題。
同時,一些用過即丟的變數也不會一直掛在廣域環境下佔記憶體,
因為全部的變數都是區域變數,使用google closure compiler等軟體進行minify化
時也能省掉更多的空間

至於在後方的括號裡丟入window,
是為了增加讀取的速度。
這裡的相關關鍵字叫做Scope Chain。

當你使用一個變數時,若javascript在當前環境找不到該名稱的變數,
就會繼續往外找尋,一直找到最外層的全域物件上還找不到時,才會報錯

而大家都知道,目前所有瀏覽器的全域物件都叫window。
所有你宣告的廣域函式跟變數都會掛在window下,
如果你想在上面的self invoking function裡使用任何廣域變數,
javascript就得多經過一次的「找不到的過程」才能找到。
但是只要你把window當成參數丟進你的self invoking function裡面,
window就會變成你自製scope裡的區域變數,
於是就省下了一層查找的功夫。
雖然我也很懷疑到底等省下多少功夫啦
但多丟參數畢竟只是動幾下手指的事而已。

而一些其他的變種
(function (window, undefined){

})(window)

在scope裡宣告了undefined這個變數,
但是在自我執行時又不丟給他,
如此便能夠完全確定你在使用undefined時代表的真的是undefined,
(是的,undefined是可以改變值的)

而這種
(function ($){

})(jQuery)
跟傳window進去的意義是一樣的
會這樣使用的人應該是認為他在這個scope裡面使用到的廣域變數只有jQuery一個,
所以只丟jQuery進去,省去了在scope裡面再次宣告的功夫。

另外,jQuery的$縮寫是有可能改變的,
(通常在你同時使用其他以$為縮寫的library時)
因此這種方法也兼顧了相容性。

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 1.164.71.67

--
※ 看板: dinos 文章推薦值: 0 目前人氣: 0 累積人氣: 297 
作者 mrbigmouth 的最新發文:
  • +71 [F/GO][情報] 自己開發的戰鬥模擬器 - TypeMoon 板
    作者: 1.164.69.47 (台灣) 2017-05-29 17:11:53
    網址: 原始碼: Bug回報區: 資料來源: 我是臺版才入坑的, 玩了這段時間後深深感到FGO戰鬥數據的各種不直覺, (我說那個傷害公式一開始先把面板ATK先乘上0.23是怎麼回事!) 總是在出牌的時 …
    93F 71推
  • +31 [問題] 教你學程式設計的遊戲 - C_Chat 板
    作者: 211.75.132.13 (台灣) 2016-10-20 11:53:04
    想了很久不知道該去哪個板發問, 但算是跟本板扯上一點關係而且又高人氣,所以在這邊求助了。 m(_ _)m 最近需要寫一個「讓不懂程式的人也能輕鬆寫程式」的程式, 但在介面設計上遇到難題,難以做到「有足 …
    52F 31推
  • Re: [問題] javascript 函數的提升 - Ajax 板
    作者: 211.75.132.13 (台灣) 2016-05-12 16:37:16
    兩個問題其實是一個解答, function two() { } 這種直接以function開頭的宣告語法是一個包含了「宣告」與「定義」的動作: 「宣告一個名稱為two的function並定義其內容」 …
  • +3 Re: [問題] 有辦法印出this的內容嗎? - Ajax 板
    作者: 211.75.132.13 (台灣) 2016-05-10 11:47:32
    對 : 你一直搞混了整件事的先後順序, 首先,「在幾乎所有語言中」, 等號指定式,也就是'xxx = ooo;'這種語法在執行時, 一定是ooo先執行完畢,才會執行等號,將結果回傳 …
    3F 3推
  • +7 [問卦] 有沒有炸蝦都不炸蝦的八卦? - Gossiping 板
    作者: 1.164.56.34 (台灣) 2014-09-13 19:55:16
    前幾天逛夜市看到有人賣炸蝦, 外面裹了一層厚厚的麵粉,用叉子從蝦子尾部叉進去豎起來賣的那種。 看它擺出來的炸蝦真的是又粗又長,看起來就很好吃的樣子, 雖然有點小貴但還是買下來嘗鮮, 但第一口咬下去感覺 …
    13F 7推
點此顯示更多發文記錄
分享網址: 複製 已複製
guest
x)推文 r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇