【譯】stackoverflow 關於JavsScript的熱門問答

Q1:javascript的閉包是如何工做的?

正如愛因斯坦所說的:javascript

若是你不能把它解釋給一個六歲的小孩,說明你對它還不夠了解。java

我曾嘗試向一個27歲的朋友解釋js閉包而且徹底失敗了。你會如何向一個有概念(例如,函數,變量等)的人解釋,來彌補閉包知識,但不理解閉包自己?jquery

Answers:

不管什麼時候你看到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參數定義的,也能夠訪問變量tmpapi

這就是一個閉包。函數沒有任何返回的時候就被稱爲閉包。簡單地訪問即時詞法做用域(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 仍然能夠指向 xtmp,即便它再也不直接範圍內。安全

然而,由於 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' 都是)閉包

建立多個閉包函數是可能的,或者經過返回他們的列表,或者經過設置他們的全局變量。全部這些將指向同上面的xtmp,他們不會拷貝他們自己。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對象引用的內存泄漏的基礎

原文連接:http://stackoverflow.com/ques...

Q2:我如何使用jQuery作一個重定向頁面?

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";

原文連接:http://stackoverflow.com/ques...

Q3:測試是否有東西被隱藏

問題描述:

在jQuery中,能夠切換元素的可見性,使用方法.hide(), .show() 或者.toggle().

使用jQuery,你如何測試一個元素是可見的仍是隱藏的?

Best Answers:

由於這個問題是指一種單一的元素,因此該代碼可能更適合:

// 檢查display:[none|block], 忽略 visible:[true|false]
$(element).is(":visible");

Other Answers:

你可使用hidden選擇器:

// 匹配的是隱藏的全部元素
$('element:hidden')

visible選擇器:

// 匹配全部可見的元素
$('element:visible')

問題連接:http://stackoverflow.com/ques...

Q4:"use strict"在js中的做用是什麼,其背後的思考是什麼?

問題描述:

最近,我運行個人一些JavaScript代碼經過CrockfordJSLint的,它給瞭如下錯誤:

Problem at line 1 character 1: Missing "use strict" statement.

作了一些搜索,我意識到是有些人添加了「use strict」到他們的JavaScript代碼中。有一次,我添加了該聲明,錯誤就中止出現了。不幸的是,谷歌並無透露太多這字符串聲明的歷史的背後。固然,它必定和javascript如何被瀏覽器解析有關係,但我不知道效果會怎樣。

那麼,什麼是"use strict";全部和它仍然相關聯的涵義是什麼?

當前任何瀏覽器是否對"use strict"作出反應;該字符串或是在未來作使用?

Best Answers:

這篇文章也許對你有幫助:

John Resig - ECMAScript 5 Strict Mode, JSON, and More

引用一些有趣的部分:

嚴格模式是`ECMAScript 5`中的一項新特徵,容許你把一段程序或功能放置在"strict"工做環境中。這種嚴格上下文環境防止某些行爲被採起並引起更多的異常。

而且:

嚴格的模式有助於幾個方面:

    它捕獲了一些常見的編碼錯誤,拋出異常。
    它阻止,或拋出錯誤,當相對「不安全」的行爲被採用(例如獲取全局對象)。 
    它禁用那些混淆的或者考慮不周的特徵

另外請注意,你能夠在整個文件中申請嚴格模式...或者你能夠僅在特定的函數中使用它(仍然是引用John Resig 的文章):

// 非嚴格的代碼...

(function(){
  "use strict";

  // 嚴格定義你的庫...
})();

// 非嚴格的代碼

若是你有混合使用新舊代碼,它可能會有所幫助;-)

因此,我認爲這是一個有點像"use strict",你能夠在Perl(所以得名?)中使用:它經過檢測更多可能致使破壞的事情來幫助你少犯錯誤。

原文連接:http://stackoverflow.com/ques...

Q5:如何檢測一個字符串包含另外一個子字符串?

問題描述:

javascript中,我如何檢測一個字符串包含另外一個子字符串。一般我會想到String.contains()方法,但彷佛沒有一個。

Best Answers:

indexOf返回一個字符串在其餘字符串中的位置。若是沒找到,它會返回-1

var s = "foo";
 alert(s.indexOf("oo") > -1);

原文地址:http://stackoverflow.com/ques...

Q6:我如何在JavaScript中得到查詢字符串的值?

問題描述:

是否有一個經過jQuery無插件查詢字符串值的方式(或者沒有)。
若是是,怎麼作?若是不是,是否有一款能夠這麼作的插件?

Best Answers:

你不須要經過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');

問題連接:http://stackoverflow.com/ques...

Q7:var functionName = function() {} vs function functionName() {}

問題描述:

我最近開始維護別人的JavaScript代碼。我修復bug,增長功能,也試圖整理代碼並使其更加一致。

以前的開發人員使用兩種函數聲明方式,我沒法弄清是否這背後有或沒有解決的緣由。

兩種方法是:

var functionOne = function() {
    // Some code
};

function functionTwo() {
    // Some code
}

使用這兩種不一樣方法的緣由是什麼,以及各自的利弊是什麼?

Best Answers:

所不一樣的是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的值。

原文連接:http://stackoverflow.com/ques...

Q8:JavaScript 中應該用 "==" 仍是 "==="?

問題描述:

我用JSLint來檢查javascript,當我在作相似比較idSele_UNVEHtype.value.length == 0的時候,接着它返回許多建議用===(三個等號)來替換==(兩個等號)

===來取代==是否有性能優點?

當有許多比較操做符存在的時候,任何性能的改進都將很受歡迎。

若是沒有類型轉換髮生,性能會超過==

Best Answers:

恆等式(===)操做符

參考文獻:JavaScript教程:比較運算符

==操做符在作任意按需類型轉換後將比較相等性,而===操做符並不會, ===運算符將不作轉換,因此若是兩值不同類型===將返回false。這種狀況下,===將更快,並可能比==返回不一樣的結果。在全部其餘狀況下的性能都是同樣的。

引用 Douglas CrockfordJavaScript: 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://www.ecma-international...

原文連接:http://stackoverflow.com/ques...

Q9:克隆一個對象的最有效的方法是什麼?

問題描述

克隆一個js對象的最有效的方法是什麼?我已經見過obj = eval(uneval(o));被使用,可是目前僅有Firefox支持。在 Mootools 1.2,我已經作了相似obj = JSON.decode(JSON.encode(o));的事情,可是存在效率問題

我也見過遞歸複製功能的各類缺陷。我很驚訝,沒有規範的解決方案存在。

Best Answers:

注:這是另外一個答覆,沒有對這個問題做出恰當的迴應。若是你但願快速複製一個對象請參考:[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的核心而且在插件裏也有重大的做用

Other answers:

彷佛沒有一個內置的方法,你能夠嘗試:

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;
}

原文連接:http://stackoverflow.com/ques...

Q10:如何從一個JavaScript對象中刪除一個屬性

問題描述:

我是這麼建立一個對象的:

var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

new myJSONObject結束的移除屬性regex的最好方法是什麼?

var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI"};

Best Answers:

delete myJSONObject.regex;
// or,
delete myJSONObject['regex'];
// or,
var prop = "regex";
delete myJSONObject[prop];

參考:understanding delete

Other Answers:

var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

delete myJSONObject.regex;

alert ( myJSONObject.regex); // alerts: undefined

這種方法在火狐和IE下起做用,我我的認爲在其餘瀏覽器也起做用

問題連接:http://stackoverflow.com/ques...

相關文章
相關標籤/搜索