JavaScript中需要注意的幾個問題


  JavaScript是一門弱語言,她使用起來不像C/C++那樣有十分繁瑣的內存管理、類型定義等,所以學習JavaScript的門檻相對來說也比較低。門檻低並不意味着這門語言很簡單,我們在使用的時候會遇到各種千奇百怪的問題,有些是因為瀏覽器的兼容性引起的,有些是因為JS語法本身所引起的,還有些是因為ECMAScript標准的改變而引起的,總之,這樣的問題很多,下面列舉

幾個比較容易忽略的點

  1. switch的case判斷

var t = event.keyCode;
switch (t) {
   case '65':
      alert("Yay!");
      break;
}

  當keycode為65時,你會發現,咦?怎么木有alert! 這里需要明確的是,switch在判斷的時候使用的是全等號“===”,全等號在比較的時候首先看數據類型是不是一樣的,而在這里,t是Number類型,而'65'是String。

 

  2. 嚴格模式下this≠window

"use strict";
var global = (function() {
    console.log(this); //undefined
})();

  有時候我們需要用global來緩存this這個全局環境(可能是window,也可能是其他的,比如在Worker中沒有window對象,用self代表Global),但是在嚴格模式下函數作用域返回的this為undefined,一般,我們可以采用如下方式獲取到Global對象:

"use strict";
var global = (function() {
    var t = new Function("return this")();
    console.log(t);
})();

或者:

"use strict";
var global = (function() {
    var t = window.eval("this");
    console.log(t);
})();

  因為new Function是在全局作用域上執行的,所以返回的是Global對象,下面的eval需要一起注意,eval前如果不交window,那它便處於function作用域中(javascript利用function里分隔作用域),自然不會返回window或者全局對象。使用Function要注意一點:

(function () {
   var local = 1;
   new Function("console.log(typeof local);")(); // logs undefined
}());

  new Function工作在Global作用域鏈下,所以是訪問不到匿名函數中local的~

 

  3. 變量提升(Hoisting)

var t = "global";
function foo(){
    console.log(t); //undefined
    return; 
   var t = "local"; }

  這是一個老生常談的問題,var最好不好到處散布。所謂的變量提升,在這里存在兩個作用域,一個是Global作用域,他下面有t和foo這兩個變量,而foo指向的是foo作用域,foo作用域下有一個t變量,畫個圖演示下吧

[Global Scope] |----- t   [String] undefined -> "global"
    |----- foo [Reference] [foo Scope]

[foo Scope] |----- t   [String] undefined -> "local"

  剛進入全局作用域鏈的時候,程序掃描到t和foo兩個變量,於是給這個t賦值為undefined,掃面完了之后,看到t有值,於是給賦值”global“,foo指向[foo Scope],於是進入[foo Scope],繼續掃描函數作用域鏈下的變量,發現目標t之后,賦值為undefined,在console.log時,是這樣的:

var t = "global";
function foo(){
    var t; // 等同於 -> var t = undefined;
    console.log(t); //undefined 
return;  
var t = "local";
}

  上面的例子寫不寫return結果都是一樣的,加return,只是為了更好的表達變量提升這個動作的存在。一般比較推薦的變量定義方式:

function foo(a, b, c) {
    var x = 1,
        bar,
        baz = "something";
}

  一個var,后邊連着一串變量的定義。

 

附:javascript嚴格模式下要注意的地方(轉自次碳酸鈷

 1. 變量必須聲明才能使用

"use strict";
a=1; //缺少var語句做聲明,因此報錯
"use strict";
var a=b=1; //錯誤 b未聲明

 

 2. 函數聲明語句(不包括表達式)不允許在普通代碼塊(不包括閉包)中使用

"use strict";
(function(){
  //閉包中是允許使用函數聲明語句的
  function func(){};
})();
{
  var f=function(){}; //函數聲明表達式允許
  function func(){}; //函數聲明語句在普通閉包中,錯誤
};

3. 閉包內的this不指向Global對象

"use strict";
(function(){
  alert(this); //輸出undefined
})();

4. 對象屬性和函數形參不能重復聲明

"use strict";
var o={a:1,a:1};
//這個對象定義了兩個a屬性,因此報錯
"use strict";
function func(a,a){};
//這個函數的兩個形參都是a,因此報錯

5. eval擁有類似閉包的作用域

"use strict";
var a=1,b=1;
eval("var a=2");
window.eval("var b=2");
alert(a); //輸出1 因為運行的a變成了eval作用域的局部變量
alert(b); //輸出2 window.eval依然是全局作用域

6. callee和caller屬性無法使用

"use strict";
function func(){
  return arguments.callee; //錯誤 callee無法使用
};
func();

7. with語句無法使用

"use strict";
with({});

8. 八進制數字常量無法使用

"use strict";
var a=0999; //十進制,可以使用
var b=0123; //八禁止,無法使用

9. 普通模式下的一些無效操作變成錯誤

"use strict";
var a=1;
delete a;
//錯誤 無法刪除var聲明的變量
"use strict";
var o={get a(){}};
o.a=1;
//錯誤 給只讀屬性賦值

 

簡單總結這么多,推薦“次碳酸鈷”童鞋的博客,細致入微、內容深刻,博客入口:http://www.web-tinker.com

關於JavaScript strict mode的詳細介紹,請移步:MDN Strict_mode

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM