正如愛因斯坦所說的:javascript
若是你不能把它解釋給一個六歲的小孩,說明你對它還不夠了解。java
我曾嘗試向一個27歲的朋友解釋js
閉包而且徹底失敗了。你會如何向一個有概念(例如,函數,變量等)的人解釋,來彌補閉包知識,但不理解閉包自己?jquery
不管什麼時候你看到function
關鍵字在另外一個函數內部,那麼內部函數將可訪問外部函數的變量。json
function foo(x) { var tmp = 3; function bar(y) { alert(x + y + (++tmp)); // will alert 16 } bar(10); } foo(2);
這將老是彈出16
,由於函數bar
能夠訪問變量 x
,它是做爲foo
參數定義的,也能夠訪問變量tmp
。api
這就是一個閉包。函數沒有任何返回的時候就被稱爲閉包。簡單地訪問即時詞法做用域(immediate lexical scope
)外的變量建立了一個閉包。瀏覽器
function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); // will also alert 16 } } var bar = foo(2); // bar is now a closure. bar(10);
上面的函數也會彈出16,由於 bar
仍然能夠指向 x
和 tmp
,即便它再也不直接範圍內。安全
然而,由於 tmp
仍然在bar
的閉包內部閒逛,它也正在增長。每次你調用bar
的時候它會被增長。
最簡單的閉包的例子是這個:session
var a = 10; var b = 6; function test() { console.log(a); // will output 10 console.log(b); // will output 6 } test();
當一個js
函數被調用的時候,一個新的執行上下文環境就被建立了。函數參數和父對象一塊兒,這個執行上下文也接收全部的外部聲明的變量(在上面的例子,'a'
和 'b'
都是)閉包
建立多個閉包函數是可能的,或者經過返回他們的列表,或者經過設置他們的全局變量。全部這些將指向同上面的x
和tmp
,他們不會拷貝他們自己。ecmascript
這裏的數字 x
是字面量的數字。和js
其餘字面量同樣,當foo
被調用,數字 x
就被複制到 foo
內做爲它的 參數 x
另外一方面,當處理對象的時候,js
總會使用引用。若是說,你用一個Object
來調用foo
,閉包將會返回最先引用的Object
function foo(x) { var tmp = 3; return function (y) { alert(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; alert(x.memb); } } var age = 2; var bar = foo(age); // bar is now a closure referencing age. bar(10);
果真,每次調用bar(10)
都將增長x.memb
。這也許不是所預期的,x
僅僅是指向一樣的對象 做爲age
變量!通過幾回調用bar
以後,age.memb
將是2!這是與HTML
對象引用的內存泄漏的基礎
jQuery
是沒有必要的,而且window.location.replace(...)
將最佳模擬HTTP
重定向。
這比使用window.location.href =
要好,由於replace()
並不把起始頁放入會話歷史(session history
)裏,這意味着用戶不會陷入永無休止的後退按鈕的窘境。若是你想要模擬人點擊一個連接,請使用location.href
。若是要模擬一個HTTP
重定向,使用location.replace
。
例如:
// 相似HTTP重定向的行爲 window.location.replace("http://stackoverflow.com"); // 相似點擊一個連接的行爲 window.location.href = "http://stackoverflow.com";
在jQuery中,能夠切換元素的可見性,使用方法.hide(), .show() 或者.toggle(). 使用jQuery,你如何測試一個元素是可見的仍是隱藏的?
由於這個問題是指一種單一的元素,因此該代碼可能更適合:
// 檢查display:[none|block], 忽略 visible:[true|false] $(element).is(":visible");
你可使用hidden
選擇器:
// 匹配的是隱藏的全部元素 $('element:hidden')
和visible
選擇器:
// 匹配全部可見的元素 $('element:visible')
最近,我運行個人一些JavaScript
代碼經過Crockford
的JSLint
的,它給瞭如下錯誤:
Problem at line 1 character 1: Missing "use strict" statement.
作了一些搜索,我意識到是有些人添加了「use strict」
到他們的JavaScript
代碼中。有一次,我添加了該聲明,錯誤就中止出現了。不幸的是,谷歌並無透露太多這字符串聲明的歷史的背後。固然,它必定和javascript
如何被瀏覽器解析有關係,但我不知道效果會怎樣。
那麼,什麼是"use strict"
;全部和它仍然相關聯的涵義是什麼?
當前任何瀏覽器是否對"use strict"
作出反應;該字符串或是在未來作使用?
這篇文章也許對你有幫助:
John Resig - ECMAScript 5 Strict Mode, JSON, and More
引用一些有趣的部分:
嚴格模式是`ECMAScript 5`中的一項新特徵,容許你把一段程序或功能放置在"strict"工做環境中。這種嚴格上下文環境防止某些行爲被採起並引起更多的異常。
而且:
嚴格的模式有助於幾個方面: 它捕獲了一些常見的編碼錯誤,拋出異常。 它阻止,或拋出錯誤,當相對「不安全」的行爲被採用(例如獲取全局對象)。 它禁用那些混淆的或者考慮不周的特徵
另外請注意,你能夠在整個文件中申請嚴格模式
...或者你能夠僅在特定的函數中使用它(仍然是引用John Resig
的文章):
// 非嚴格的代碼... (function(){ "use strict"; // 嚴格定義你的庫... })(); // 非嚴格的代碼
若是你有混合使用新舊代碼,它可能會有所幫助;-)
因此,我認爲這是一個有點像"use strict"
,你能夠在Perl
(所以得名?)中使用:它經過檢測更多可能致使破壞的事情來幫助你少犯錯誤。
在javascript
中,我如何檢測一個字符串包含另外一個子字符串。一般我會想到String.contains()
方法,但彷佛沒有一個。
indexOf
返回一個字符串在其餘字符串中的位置。若是沒找到,它會返回-1
var s = "foo"; alert(s.indexOf("oo") > -1);
是否有一個經過jQuery
無插件查詢字符串值的方式(或者沒有)。
若是是,怎麼作?若是不是,是否有一款能夠這麼作的插件?
你不須要經過jQuery
就能夠達到那個目的。你能夠僅僅使用純javascript
:
function getParameterByName(name) { name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); }
用法:
var prodId = getParameterByName('prodId');
我最近開始維護別人的JavaScript
代碼。我修復bug
,增長功能,也試圖整理代碼並使其更加一致。
以前的開發人員使用兩種函數聲明方式,我沒法弄清是否這背後有或沒有解決的緣由。
兩種方法是:
var functionOne = function() { // Some code }; function functionTwo() { // Some code }
使用這兩種不一樣方法的緣由是什麼,以及各自的利弊是什麼?
所不一樣的是functionOne
被定義在運行時,而functionTwo
被限定在分析時的腳本塊。例如:
<script> // Error functionOne(); var functionOne = function() { }; </script> <script> // No error functionTwo(); function functionTwo() { } </script>
這也意味着在嚴格的模式下,你不能有條件地使用第二語法定義函數:
<script> "use strict"; if (test) { // Error function functionThree() { doSomething(); } } </script>
若是沒有"use strict"
這將不會致使一個錯誤 而且 functionThree
將被定義無關test
的值。
我用JSLint
來檢查javascript
,當我在作相似比較idSele_UNVEHtype.value.length == 0
的時候,接着它返回許多建議用===
(三個等號)來替換==
(兩個等號)
用 ===
來取代==
是否有性能優點?
當有許多比較操做符存在的時候,任何性能的改進都將很受歡迎。
若是沒有類型轉換髮生,性能會超過==
?
恆等式(===)操做符
參考文獻:JavaScript教程:比較運算符
==
操做符在作任意按需類型轉換後將比較相等性,而===
操做符並不會, ===
運算符將不作轉換,因此若是兩值不同類型===
將返回false
。這種狀況下,===
將更快,並可能比==
返回不一樣的結果。在全部其餘狀況下的性能都是同樣的。
引用 Douglas Crockford
的JavaScript: The Good Parts
javascript擁有兩套等性運算符: `===`和`!==`,和他們邪惡的雙胞胎 `==`和`!=`。好的那一個會按你所指望的方式工做。若是兩個操做數是相同的類型,具備相同的值,那麼`===`產生`true`,`!==`產生`false`。當操做數具備相同類型時,邪惡雙胞胎作正確的事,可是若是他們是不一樣類型,它們試圖強制值。他們這麼作的規格是複雜難記的,這裏有一些有趣的例子: '' == '0' // false 0 == '' // true 0 == '0' // true false == 'false' // false false == '0' // true false == undefined // false false == null // false null == undefined // true ' \t\r\n ' == 0 // true
個人建議是不要使用邪惡的雙胞胎。相反,老是用===
和!==
。全部的比較只是產生虛假的= = =運算符。用===
操做符的全部的比較僅顯示false
更新:
var a = [1,2,3]; var b = [1,2,3]; var c = { x: 1, y: 2 }; var d = { x: 1, y: 2 }; var e = "text"; var f = "te" + "xt"; a == b // false a === b // false c == d // false c === d // false e == f // true e === f // true
特殊狀況下,當你比較字面量和對象的時候,考慮到它的toString
或者valueOf
方法。例如,考慮比較由字符串構造函數建立的字符串對象和字符串字面量
"abc" == new String("abc") // true "abc" === new String("abc") // false
這裏的==
操做符正在檢查這兩個對象的值並返回true
,可是鑑於它們不是相同類型而且===
返回false
。哪個是正確的?這實際上取決於你想要比較什麼。個人建議是徹底繞過這個問題,只是不使用字符串構造函數建立字符串對象。
原文連接:http://stackoverflow.com/ques...
克隆一個js
對象的最有效的方法是什麼?我已經見過obj = eval(uneval(o));
被使用,可是目前僅有Firefox支持。在 Mootools 1.2
,我已經作了相似obj = JSON.decode(JSON.encode(o));
的事情,可是存在效率問題
我也見過遞歸複製功能的各類缺陷。我很驚訝,沒有規範的解決方案存在。
注:這是另外一個答覆,沒有對這個問題做出恰當的迴應。若是你但願快速複製一個對象請參考:[Corban's advice in his
answer][4] 他對這個問題的回答。
我想指出,jQuery
中的.clone()
方法只克隆DOM
元素。爲了克隆JavaScript
對象,你須要這麼作:
// 淺拷貝 var newObject = jQuery.extend({}, oldObject); // 深拷貝 var newObject = jQuery.extend(true, {}, oldObject);
更多信息請參考:http://api.jquery.com/jQuery....
我還想指出,深拷貝其實比上面所示聰明得多 - 它是可以避免不少陷阱(例如,想深擴展DOM
元素)。它被頻繁地用於jQuery
的核心而且在插件裏也有重大的做用
彷佛沒有一個內置的方法,你能夠嘗試:
function clone(obj) { if(obj == null || typeof(obj) != 'object') return obj; var temp = obj.constructor(); // changed for(var key in obj) { if(obj.hasOwnProperty(key)) { temp[key] = clone(obj[key]); } } return temp; }
我是這麼建立一個對象的:
var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
以new myJSONObject
結束的移除屬性regex
的最好方法是什麼?
var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI"};
delete myJSONObject.regex; // or, delete myJSONObject['regex']; // or, var prop = "regex"; delete myJSONObject[prop];
var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; delete myJSONObject.regex; alert ( myJSONObject.regex); // alerts: undefined
這種方法在火狐和IE
下起做用,我我的認爲在其餘瀏覽器也起做用