CONTENT(目錄) 前言 Variable declearation:three rules you can break 1.Don't set var statement in a block 2.Don't set var statement in a loop 3.Set a variab ...
CONTENT(目錄)
Variable declearation:three rules you can break
1.Don't set var statement in a block
2.Don't set var statement in a loop
3.Set a variable corresponding var stamement
Pitfall 1:variable is function-scoped.
Pitfall 2:they can be capture in closurse.
最近看的書,怎麼說呢?就不多也不少。本想等技術成熟些,再來寫博客,和大家一起分享,一起進步,互相交朋友。
但是,突然發現,最初看的知識,如果不一直在腦袋中回憶,好像雲里霧裡,有些知其然不知其所以然的味道。想起要再回顧一下,就又要從一大堆的材料中找到這些知識,效率十分低下,
心想這麼做也不是長久之計。但又不是高手,只好將這篇放入隨筆記錄,起碼也算是個安身立命之所。
本人目前還是在校生,算是渣渣,一心想學好技術,這裡便是我的起點了,寫的不好的請大神們輕拍。
說到變數,我們會想到變數名的命名規則,變數的類型,變數的聲明,變數作用域等.變數的命名規則有匈牙利命名法和大小駝峰法。變數的類型有六種,其中五種原始類型:
分別是undefined,null,Number,String,Boolean.其他的全是object(對象).這些只要有點編程知識的,基本都懂我們就不多加討論。有興趣的可以私聊我或者自行百度。
點擊可看大圖。
變數的聲明和作用域是我們重點要說明的,畢竟和我們學的C/C++,java等還是有些不一樣的。
Variable declearation:three rules you can break
Don't set var statement in a block
不要將var語句放在塊區域中。我們平時所學的Java和c/c++是支持塊作用域的,在變數所聲明和定義的塊區域外,我們無法使用這個變數。
但是在JS中,卻不是這樣,我們來看下麵的代碼:
1 functions fn(x,y){ 2 if(x>y){ 3 var temp = x; 4 x = y; 5 y = temp; 6 } 7 }
記住,在JS中,用 var 聲明的變數,存在一個變數提升的問題(hoisted)。就是講變數的聲明提升到函數體的第一行,而賦值語句還是呆在原來的地方。實際效果如下:
function fn(x,y){ var temp; if(x>y){ temp = x; x = y; y = temp; } }
還有一點需要註意的是你不得不小心使用每個偽塊作用域(pseudo-block-local)的變數一次,如果你再次聲明這個變數,它會保存當前的值。如下:
function fn(x,y){ if(x<0){ var temp; console.log(temp);//undefind temp = 3; .... } if(y<0){ var temp;// declared again console.log(temp);//3 ... } } fn(-1,-1);
Don't set a var statement in a loop
不要在迴圈體內聲明變數,原理和不要在塊區域里聲明變數一樣。如下:
functions fn(){ var temp;//do this 好像說這麼做速度會快些。 for(var i=0;i<100;i++){ var temp; //don't do this .... } }
另外再扯一個問題。使用var 聲明變數,有時候會產生一些奇怪的現在。比如:
for(var i=0; i<10;i++){ setTimeout(function(){ console.log(i); },100*i); } //輸出的結果是 10個10 具體是怎麼回事我也似懂非懂,會持續關註這個問題
解決的方案是使用立即調用函數表達式(IIFE)來獲取for迴圈每次迴圈時i的值。(看解決的方法,好像是出現了閉包(closure)的問題,但是我實在看不出來!)
for(var i=0;i<100;i++){ (function (i){ setTimeout(function(){ console.log(i); }.100*i); })(i); }
IIFE是immediately-invoked Function expression的簡寫。想瞭解詳情點擊這裡或者這裡
ES6提供了let關鍵字來聲明變數,let變數只在其代碼塊中生效,也就是塊級作用域。註意一個要點,在代碼塊內,只要是在let聲明前使用變數都是不可用的。這種現象在ES6 稱為“暫時性死區(temporal dead zone)”,簡稱為TDZ
set a variable corresponding a var statement
聲明一個變數我們就用一條var語句。
先看代碼段(1),在函數體頂端我們用一條var語句聲明瞭三個變數並賦值。再看代碼段(2),如果我們不小心漏了一個逗號(comma),在不經意間你就創建了兩個全局變數b和c。
(註:給沒用var statement 聲明的變數名賦值,會產生全局變數。) 產生這樣的原因是:a=1 沒有標點符號,javascript內部有個機制,會幫你自動加上分號(semicolon)。
有興趣的同學想瞭解什麼情況下會自動加分號,可自行百度,也可看文章底部鏈接。
再來看代碼段(3),文章作者是推薦這樣的寫法。原因有3點:
- 沒有標點符號的問題,如果你不小心遺漏了分號,自動加分號的機制會幫你加上.
- 更容易去添加或者刪除某條語句,不會有代碼段(2)產生的問題.
- 縮進很自然。
//(1) var a=1, b=2, c=3; //(2) var a=1 b=2, //全局變數產生 c=3; //(3) var a=1; var b=2; var c=3;
javascript的變數的作用域。在JS中的變數作用域是真的奇葩。本文主要講兩點:
陷阱1: 變數的作用域是函數作用域
var myvar = "global"; function fn(){
/* var myvar */ (1) console.log(myvar);//undefined if(true){
/* myvar = "local"; */ (2) var myvar = "local"; } console.log(myvar); //local }
>fn();
undefined
local
>myvar
gloabl
與前文的不要將var語句放在塊作用域的原理一樣,存在變數的提升.實際效果是註釋(1)(2)的樣子。所以最佳實踐是只在函數體開始的地方使用var。
陷阱2:閉包
functions fn(){ var myvar = "abc"; return function(){ return myvar; }; }
var f=fn();
>f()
abc
這個算是最簡單的閉包了吧。在函數里還有內層函數,通過返回內層函數將函數的值拋出來。其實要是閉包的結構太複雜,我也看不懂是否是閉包。還需努力。
需要註意兩個點:
- 不經意間分享共同的環境
- 創建一個新的環境
總結:在沒有開始寫以前,感覺很簡單。因為基本的思路已經有了,但是發現真正做起來,還是有難度的。雖然內容不多,可能還有缺陷,可足足花了3天時間。
(還有課!!!)
要考慮排版,內容的思路清晰,還有第一次使用博客園的窘境。喜歡英文的同學可以看這篇,內容基本一樣吧,在這篇文章里的第4點references(引用),
有你們關心的變數作用域,自動加分號機制,還有"strict mode"(嚴格模式),ES5應該都是“sloppy mode”; 傳送門