亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript代碼編寫中各種各樣的坑和填坑方法

2019-11-20 14:47:58
字體:
來源:轉載
供稿:網友

坑”這個字,在此的意思是“陷阱”。由于 JavaScript “弱語言”的性質,使得其在使用過程中異常的寬松靈活,但也極為容易“中招”。這些坑往往隱藏著,所以必須擦亮雙眼,才能在學習與應用 JS 的道路上走的一帆風順。

一、全局變量

JavaScript 通過函數管理作用域。在函數內部聲明的變量只在這個函數內部,函數外面不可用。另一方面,全局變量就是在任何函數外面聲明的或是未聲明直接簡單使用的。

“未聲明直接簡單使用”,指的是不用 var 關鍵字來聲明變量。這個我們已經非常清楚,避免造成隱式產生全局變量的方法就是聲明變量盡量用 var 關鍵字。

可你以為用了 var 就 ok 了?來看看這個坑:

復制代碼 代碼如下:

function foo() {
    var a = b = 0;
    // body...
}

也許你期望得到的是兩個局部變量,但 b 卻是貨真價實的全局變量。why? Because 賦值運算是自右往左的 ,所以這相當于:

復制代碼 代碼如下:
 
function foo() {
    var a = (b = 0);
    // body...
}

所以 b 是全局變量。

填坑:變量聲明,最好一個個來,別搞批發~_~;

二、變量聲明

先來看坑:

復制代碼 代碼如下:
 
myName = "global";

function foo() {
    alert(myName);
    var myName = "local";
    alert(myName);
}

foo();

乍看上去,我們預計期望兩次 alert 的結果分別為 “global” 與 “local”,但真實的結果是 “undefined” 與 “local”。why? Because 變量在同一作用域(同一函數)中,聲明都是被提至作用域頂部先進行解析的。

所以以上代碼片段的執行行為可能就像這樣:

復制代碼 代碼如下:

function foo() {
    var myName;
    alert(myName); // "undefined"
    myName = "local";
    alert(myName); // "local"
}

用另一個坑來測試下你是否真的理解了預解析:
復制代碼 代碼如下:
 
if (!("a" in window)) {
    var a = 1;
}

alert(a);

a 變量的聲明被提前到了代碼頂端,此時還未賦值。接下來進入 if 語句,判斷條件中 "a" in window 已成立(a 已被聲明為全局變量),所以判斷語句計算結果為 false,直接就跳出 if 語句了,所以 a 的值為 undefined。
復制代碼 代碼如下:

var a; // "undefined"
console.log("a" in window); // true

if (!("a" in window)) {
    var a = 1; // 不執行
}

alert(a); // "undefined"

填坑:變量聲明,最好手動置于作用域頂部,對于無法當下賦值的變量,可采取先聲明后賦值的手法。

三、函數聲明

函數聲明也是被提前至作用域頂部,先于任何表達式和語句被解析和求值的

復制代碼 代碼如下:
 
alert(typeof foo); // "function"

function foo() {
    // body...
}

可以對比一下:
復制代碼 代碼如下:

alert(typeof foo); // "undefined"

var foo = function () {
    // body...
};

明白了這個道理的你,是否還會踩以下的坑呢?

復制代碼 代碼如下:
 
function test() {
    alert("1");
}

test();

function test() {
    alert("2");
}

test();

運行以上代碼片段,看到的兩次彈窗顯示的都是 “2”,為什么不是分別為 “1” 和 “2” 呢?很簡單,test 的聲明先于 test() 被解析,由于后者覆蓋前者,所以兩次執行的結果都是 “2”。

填坑:多數情況下,我用函數表達式來代替函數聲明,特別是在一些語句塊中。

四、函數表達式

先看命名函數表達式,理所當然,就是它得有名字,例如:

復制代碼 代碼如下:
var bar = function foo() {
    // body...
};

要注意的是:函數名只對其函數內部可見。如以下坑:
復制代碼 代碼如下:
 
var bar = function foo() {
    foo(); // 正常運行
};

foo(); // 出錯:ReferenceError

填坑:盡量少用命名函數表達式(除了一些遞歸以及 debug 的用途),切勿將函數名使用于外部。

五、函數的自執行

對于函數表達式,可以通過后面加上 () 自執行,而且可在括號中傳遞參數,而函數聲明不可以??樱?BR>

復制代碼 代碼如下:
 
// (1) 這只是一個分組操作符,不是函數調用!
// 所以這里函數未被執行,依舊是個聲明
function foo(x) {
  alert(x);
}(1);

以下代碼片段分別執行都彈窗顯示 “1”,因為在 (1) 之前,都為函數表達式,所以這里的 ()非分組操作符,而為運算符,表示調用執行。

復制代碼 代碼如下:
// 標準的匿名函數表達式
var bar = function foo(x) {
  alert(x);
}(1);

// 前面的 () 將 function 聲明轉化為了表達式
(function foo(x) {
  alert(x);
})(1);

// 整個 () 內為表達式
(function foo(x) {
  alert(x);
}(1));

// new 表達式
new function foo(x) {
  alert(x);
}(1);

// &&, ||, !, +, -, ~ 等操作符(還有逗號),在函數表達式和函數聲明上消除歧義
// 所以一旦解析器知道其中一個已經是表達式了,其它的也都默認為表達式了
true && function foo(x) {
  alert(x);
}(1);

填坑:這個坑的關鍵在于,弄清楚形形色色函數表達式的實質。

六、循環中的閉包

以下演示的是一個常見的坑:

復制代碼 代碼如下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <h3>when clicking links below, show the number of its sequence</h3>
    <ul>
        <li><a href="#">link #0</a></li>
        <li><a href="#">link #1</a></li>
        <li><a href="#">link #2</a></li>
        <li><a href="#">link #3</a></li>
        <li><a href="#">link #4</a></li>
    </ul>
</body>
</html>

復制代碼 代碼如下:

var links = document.getElementsByTagName("ul")[0].getElementsByTagName("a");

for (var i = 0, l = links.length; i < l; i++) {
    links[i].onclick = function (e) {
        e.preventDefault();
        alert("You click link #" + i);
    }       
}

我們預期當點擊第 i 個鏈接時,得到此序列索引 i 的值,可實際無論點擊哪個鏈接,得到的都是 i 在循環后的最終結果:”5”。

解釋一下原因:當 alert 被調用時,for 循環內的匿名函數表達式,保持了對外部變量 i的引用(閉包),此時循環已結束,i 的值被修改為 “5”。

填坑:為了得到想要的結果,需要在每次循環中創建變量 i 的拷貝。以下演示正確的做法:

復制代碼 代碼如下:

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <h3>when clicking links below, show the number of its sequence</h3>
    <ul>
        <li><a href="#">link #0</a></li>
        <li><a href="#">link #1</a></li>
        <li><a href="#">link #2</a></li>
        <li><a href="#">link #3</a></li>
        <li><a href="#">link #4</a></li>
    </ul>
</body>
</html>

復制代碼 代碼如下:

var links = document.getElementsByTagName(“ul”)[0].getElementsByTagName(“a”);
for (var i = 0, l = links.length; i < l; i++) {
    links[i].onclick = (function (index) {
        return function (e) {
            e.preventDefault();
            alert("You click link #" + index);
        }
    })(i);
}

可以看到,(function () { ... })() 的形式,就是上文提到的 函數的自執行 ,i 作為參數傳給了 index,alert 再次執行時,它就擁有了對 index 的引用,此時這個值是不會被循環改變的。當然,明白了其原理后,你也可以這樣寫:

復制代碼 代碼如下:

for (var i = 0, l = links.length; i < l; i++) {
    (function (index) {
        links[i].onclick = function (e) {
            e.preventDefault();
            alert("You click link #" + index);
        }
    })(i);
}

It works too.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品电影在线| 亚洲国产美女久久久久| 91色视频在线导航| 日韩av毛片网| 欧美精品在线看| 91免费国产网站| 亚洲国产欧美一区二区三区久久| 欧美中文字幕第一页| 欧美国产日韩一区二区在线观看| 国产亚洲欧洲黄色| 国产日本欧美一区二区三区在线| 欧洲亚洲免费视频| 欧美疯狂做受xxxx高潮| 亚洲美女在线看| 欧美理论片在线观看| 亚洲欧洲av一区二区| 国产精品久久久久久久久久三级| 亚洲伊人一本大道中文字幕| 欧美电影免费观看网站| 欧美日韩另类视频| 欧美性猛交xxxx偷拍洗澡| 久久久精品日本| 欧美日韩亚洲精品一区二区三区| 亚洲高清一二三区| 欧美日韩国产成人在线| 欧美激情精品久久久久久| 国产狼人综合免费视频| 亚洲国产高潮在线观看| 久久99久国产精品黄毛片入口| 成人伊人精品色xxxx视频| 欧美激情欧美狂野欧美精品| 久久躁日日躁aaaaxxxx| 国产精品日本精品| 欧美国产日韩在线| 色综合老司机第九色激情| 国自产精品手机在线观看视频| 亚洲免费一级电影| 日韩精品在线视频观看| 国产精品久久一区主播| 欧美最猛性xxxxx亚洲精品| 成人在线免费观看视视频| 岛国av一区二区三区| 国产主播喷水一区二区| 欧美日本亚洲视频| 中文字幕一区日韩电影| 欧美精品在线播放| 91精品免费久久久久久久久| 亚洲一区二区中文| 亚洲男人av在线| 日韩中文字幕在线免费观看| 国产日韩欧美一二三区| 91久久精品日日躁夜夜躁国产| 国产精品日韩欧美综合| 日韩电影中文字幕av| 国产一区二区三区在线播放免费观看| 欧美黑人极品猛少妇色xxxxx| 欧美激情伊人电影| 午夜精品在线观看| 国产精品免费一区二区三区都可以| 成人免费激情视频| 午夜精品久久久久久久久久久久久| 国产91精品久久久| 亚洲日本欧美日韩高观看| 91黑丝在线观看| 久久亚洲春色中文字幕| 国产亚洲成精品久久| 疯狂蹂躏欧美一区二区精品| 91麻豆国产语对白在线观看| 7m第一福利500精品视频| 亚洲第一综合天堂另类专| 中文字幕亚洲欧美| 91精品国产高清自在线看超| 欧美激情第6页| 亚洲区bt下载| 日本精品视频在线观看| 九九热99久久久国产盗摄| 国产v综合v亚洲欧美久久| 怡红院精品视频| 国产精品久久久久91| 日韩av在线高清| 国产精品精品视频| 亚洲午夜av久久乱码| 亚洲二区在线播放视频| 日韩av中文字幕在线| 韩剧1988免费观看全集| 国产精品极品尤物在线观看| 91chinesevideo永久地址| 欧美日韩国产在线| 91麻豆国产语对白在线观看| 96精品久久久久中文字幕| 久久久欧美一区二区| 久久精品国产99国产精品澳门| 在线观看亚洲视频| 久久久久久久久久久国产| 精品人伦一区二区三区蜜桃网站| 最近2019中文免费高清视频观看www99| 全球成人中文在线| 久久久久久久91| 中文亚洲视频在线| 国产97色在线|日韩| 国产香蕉精品视频一区二区三区| 福利一区福利二区微拍刺激| 久久久久久亚洲精品不卡| 亚洲一区二区久久久久久久| 91精品国产综合久久香蕉最新版| www.亚洲人.com| 亚洲精品v欧美精品v日韩精品| 成人免费在线网址| 欧美日韩激情小视频| 91沈先生在线观看| 国产精品视频久久久| 97av在线视频免费播放| 亚洲性xxxx| 色综合久久天天综线观看| 久久久久久国产| 欧美激情成人在线视频| 国产精品你懂得| 欧美午夜性色大片在线观看| 国产成人短视频| 高清一区二区三区日本久| 日韩激情av在线播放| 成人在线视频网站| 欧美天堂在线观看| 欧美性猛交丰臀xxxxx网站| 日韩欧美在线视频观看| 欧美电影免费看| 欧美一区二三区| 国产精品99久久久久久久久| 亚洲毛茸茸少妇高潮呻吟| 91麻豆国产语对白在线观看| 2020欧美日韩在线视频| 精品国产一区二区三区久久久狼| 欧美电影免费播放| 精品香蕉在线观看视频一| 国产a级全部精品| 97精品免费视频| 第一福利永久视频精品| 欧美激情aaaa| 日韩成人av一区| 日韩精品视频在线| 国产欧美一区二区三区在线看| 日韩不卡中文字幕| 国产+人+亚洲| 欧美老少做受xxxx高潮| 亚洲成人亚洲激情| 日韩高清欧美高清| 欧美—级a级欧美特级ar全黄| 92国产精品久久久久首页| 亚洲人午夜色婷婷| 亚洲人成在线观| 亚洲欧美中文日韩在线v日本| 精品国产一区久久久| 精品久久久久久亚洲精品| 亚洲精品一区二区久| 午夜精品蜜臀一区二区三区免费| 欧美性猛交xxxx黑人猛交| 亚洲电影在线看| 中文字幕亚洲第一| 国产精品电影在线观看| 国产精品jvid在线观看蜜臀| 中文字幕一区日韩电影| 欧美精品久久久久| 国产精品欧美日韩久久| 精品日本高清在线播放|