1、全局變量與局部變量
全局變量:全局變量就是在函數的外部定義的一個在其他地方都可以調用的變量
局部變量:局部變量是相對於全局變量而言的,局部變量指的是在一個區域內存在這個變量
全局變量的創建原理是在JavaScript加載頁面的時候會自動的創建一個window對象,這個對象我們可以在方法的外部通過this去調用,我們所定義的變量其實就是對這個window對象進行添加屬性而已
myglobal = "hello"; // 不推薦寫法 console.log(myglobal); // "hello" console.log(window.myglobal); // "hello" console.log(window["myglobal"]); // "hello" console.log(this.myglobal); // "hello"
好了說一下,相信大家都知道全局變量的好處吧,全局變量就是的一個好處就是可以避免多次使用的變量被重復的定義(相對於局部變量而言)
局部變量的好處是當web頁面需要引入廣告代碼或者等其他的第三方的代碼的時候,通過創建局部變量就可以避免與第三方代碼發生沖突,創建局部變量只要在方法內響應的變量加上var就行了,說到這里我就來挖一個坑給大家填填
(function foo(){ var a=b=1; }()); console.log(b); console.log(a);
大家先不要打開調試工具,先猜一猜運行的結果是什么?好了不管你猜對還是猜錯我在這里就公布答案了
原因是我們應該要把var a=b=1;這就一分為二其中b是全局變量,a是局部變量但是他們的值是相同的,但是在方法的外部是不能訪問到局部變量,所以才會出現a未定義的提示
2、使用var創建的全局變量和隱式創建全局變量的區別?
使用var創建的全局變量可以不可以通過delete刪除
隱式創建全局變量可以通過delete刪除
從側面我們可以說明通過隱式創建全局變量不是在全局對象中創建變量,而是在全局對象創建屬性(也就是說在window對象上創建屬性)
var myglobal = "hello"; myglobal1="hello1"; function foo(){ myglobal2="hello2"; } //刪除 delete myglobal; delete myglobal1; delete myglobal2; //調試一下,看看結果
結果如下:
3、單var定義變量
function func() { var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... } //查看單var結果 console.log(myobject); console.log(i);
這樣定義的變量全部都是局部變量,而且還有還有在單一地方尋找所有的局部變量、減少代碼等好處
4、var的懸置問題
JavaScript中,你可以在函數的任何位置聲明多個var語句,並且它們就好像是在函數頂部聲明一樣發揮作用,這種行為稱為 hoisting(懸置/置頂解析/預解析)
這個定義可能有些雲里霧里,我們就來寫一個演示看看理解理解
myglobal="leslie"; function foo(){ console.log(myglobal);//undefined var myglobal="les"; console.log(myglobal);//les } foo();
運行的結果如注釋所注,可能有些朋友會有所疑惑,其實這個就是一個var懸置的問題,在foo方法中我們創建了另外的一個局部變量myglobal,這個局部變量就會雖然看起來沒有置頂,但是實際上在運行的過程中會將這個局部變量置頂,由於新創建的變量表現為undefined,所以這個時候第一句打印出來的值就是undefined,運行代碼如下:
myglobal="leslie"; function foo(){ var myglobal;//undefined console.log(myglobal);//undefined var myglobal="les"; console.log(myglobal);//les } foo();
5、為對象模型添加方法以及遍歷去除原始模型的方法
1、創建一個對象模型
// 對象 var man = { hands: 2, legs: 2, heads: 1 };
2、為對象添加方法
// 對象 var man = { hands: 2, legs: 2, heads: 1 }; // 在代碼的某個地方 // 一個方法添加給了所有對象 if (typeof Object.prototype.clone === "undefined") { Object.prototype.clone = function () {}; }
3、過濾對象模型的方法
// 1. // for-in 循環 for (var i in man) { if (man.hasOwnProperty(i)) { // 過濾 console.log(i, ":", man[i]); } } /* 控制台顯示結果 hands : 2 legs : 2 heads : 1 */
雖然可以為對象模型添加屬性或者是方法,但是這個一般我們是不推薦使用的, 因為這樣會造成團隊溝通障礙以及其他的問題
6、避免發生隱式轉換
JavaScript在比較的時候會發生隱式轉換,為了避免發生隱式轉換我們應該使用"==="和“!==”來代替"=="和“!=”
var test=1; if(test===true){ alert("this is one test"); } if (test==true) { alert("this is two test"); };
結果:
7、慎重使用eval()
在使用eval來動態加載腳本的時候,由於安全問題以及eval會污染環境
var un="test"; console.log(typeof un);//string console.log(typeof deux); // "undefined" console.log(typeof trois); // "undefined" var jsstring = "var un = 5; console.log(un);"; eval(jsstring); // un=5; jsstring = "var deux = 2; console.log(deux);"; new Function(jsstring)(); // deux=2; jsstring = "var trois = 3; console.log(trois);"; (function () { eval(jsstring); }()); // trois=3 console.log(typeof un); // number console.log(un); console.log(typeof deux); // "undefined" console.log(typeof trois); // "undefined"
從上面的代碼我們可以分析得出直接使用eval會污染原來的環境(將un原來的string修改為number),較為推薦的是使用第三種方法,即解決了這個問題同時還比較符合編程的代碼習慣
上面其實是實現對方法外部的eval的隔離,其實在方法中我們也可以使用相同的方法來達到隔離的作用
(function () { jsstring = "var trois = 3; console.log(trois);"; (function () { jsstring="var trois=10;console.log(trois);"; eval(jsstring); }()); console.log(jsstring); }());
打印的結果是
除了使用兩種相同的方法套接外,還可以使用new function(){}的這種方法的套接
其實說白了就是通過將eval放置在一個局部的作用域中運行,其實還有一種更加簡便的方法可以實現(這是我自己想出來的方法,不對的地方請大家指正)
(function () { jsstring = "var trois = 3; console.log(trois);"; { jsstring="var trois=10;console.log(trois);"; eval(jsstring); } console.log(jsstring); }());
這樣運行的結果也是同上一個實例一樣
8、編寫規范
除了要注意這些問題編寫規范也是很重要的
對於構造函數,可以使用大駝峰式命名法(upper camel case),如MyConstructor()
。對於函數和方法名稱,你可以使用小駝峰式命名法(lower camel case),像是myFunction(), calculateArea()
和getFirstName()
。常量的命名我們一般用大寫,例如:var MAX=1