本系列屬於進階系列,語經常使用語法等不在本系列介紹範圍以內。javascript
在我剛開始作一個程序員並開發項目的時候,我老是喜歡使用開發語言的各類特性,每次m$發佈新版C#的時候我老是會把開發者預覽版下好,親自體驗,並指望從中得到快感,每次使用新的語言進行程序設計的時候,我老是喜歡掌控他有趣的地方,儘管不少與軟件工程有悖。這彷佛讓我出過不少風頭,別人的問題彷佛沒有什麼能難倒個人,後來在我開始從工程領域思考問題的時候,我發現不少特色給我帶來的"編程快感"引起的麻煩超過了快感自己的價值,不少地方難以被同項目的人理解,這些奇淫技巧在我學習jquery源碼的時候也給我帶來了不小的麻煩(jq源碼使用了大量js技巧),沒有相比於更工程化的backbone.js的源碼易於學習,這一年我學會了在中間作取捨,這是必須的。
不過我認爲我快速學習的能力須要保留,我通常把我學過的高級編程語言分爲「面向過程」,「面向對象」,「函數式」,「併發式」,這讓我學一個新語言的時候會很是之快速,不過大多數語言都是把特色混雜在一塊兒了。java
本系列內容爲本人平時項目實踐和參照MDN,MSDN,《javascript語言精粹》,《Effective Javascript》等資料,而且整理本身EverNote的平常積累整理所寫,時間太長有一些代碼樣例來源不可考。本系列不容許任何形式的轉載,謝謝。 from yeanzhijquery
JavaScript 是一種面向對象的動態語言,它包含類型、運算符、核心對象(core objects)和方法。不過須要注意的一個主要區別是 JavaScript 不支持類,類這一律念在 JavaScript 經過對象原型(object prototype)實現。另外一個主要區別是 JavaScript 中的函數也是對象,JavaScript 容許函數在包含可執行代碼的同時,能像其餘對象同樣被傳遞。程序員
1,JavaScript 採用「IEEE 754 標準定義的雙精度64位格式」,也就是說不區分整形和浮點數,js中一切數字都是用浮點數表示。
2,js中算數除了+,-,*,/等常規運算符外,在Math中還定義了一些高級數學函數,在使用以前請肯定傳入的參數是數字,可使用Numbetr(),parseInt(),或者parseFloat()轉化成數字並用isNaN()來斷定,若是返回的是數字,那麼!isNaN(theNumber)將返回true。web
注意:Number()的強制類型轉換與parseInt()和parseFloat()方法的處理方式類似,只是它轉換的是整個值,而不是部分值。parseInt()和parseFloat()函數會嘗試逐個解析字符串中的字符,直到趕上一個沒法被解析成數字的字符,而後返回該字符前全部數字字符組成的數字。如「3.4.5」被轉換成「3.4」,用Number()進行強制類型轉換將返回NAN,同理使用運算符 + 將字符串轉換成數字,只要字符串中含有沒法被解析成數字的字符,該字符串都將被轉換成 NaN。若是字符串值能被完整地轉換,Number()將判斷是調用parseInt()仍是parseFloat()。編程
JavaScript 中的字符串是一串字符序列。更準確地說,它們是一串由Unicode 字符構成的字符序列,每個字符由一個 16 位二進制數表示。瀏覽器
這個類型的變量有兩個可能的值,分別是 true 和 false(二者都是關鍵字)。根據具體須要,JavaScript 按照以下規則將變量轉換成布爾類型:
1,false、0、空字符串("")、NaN、null 和 undefined 被轉換爲 false,
2,其餘值被轉換爲 true閉包
JavaScript 中 null 和 undefined 是不一樣的,前者表示一個空值(non-value),後者是「undefined(未定義)」類型的對象,表示一個尚未被分配的值。不過undefined==null 返回的是true,也就是說在實際編程中他倆誤用對代碼幾乎沒什麼影響。併發
1,在 JavaScript 中聲明一個新變量的方法是使用關鍵字 var,
2,在js1.7中 let 關鍵字被引入,咱們可使用 let 語句聲明一個變量,該變量的範圍限於聲明它的塊中。 能夠在聲明變量時爲變量賦值,也能夠稍後在腳本中給變量賦值。
使用 let 聲明的變量,在聲明前沒法使用,不然將會致使錯誤。
若是未在 let 語句中初始化您的變量,則將自動爲其分配 JavaScript 值 undefined。編程語言
var i = 10;{ let i = 2; // 這, i = 2.}// 這裏, i = 10.
經過對比let和var更有助於理解這個關鍵字
1,全局中使用這兩個沒有任何差異
let me = 'go'; //和下面等同var i = 'able';
2,函數做用域裏面
function ingWithinEstablishedParameters() { let terOfRecommendation = 'awesome worker!'; var sityCheerleading = 'go!'; //沒什麼區別};
3,塊做用域中這裏是差異
function allyIlliterate() { //變量tuce 在這裏不可用 for( let tuce = 0; tuce < 5; tuce++ ) { //tuce is only visible in here (and in the for() parentheses) }; //變量tuce 在這裏不可用};function byE40() { //變量nish 在這裏可用 for( var nish = 0; nish < 5; nish++ ) { //nish is visible to the whole function }; //變量nish 在這裏可用};
4,let還能夠建立本身的封閉塊,固然一遍我不推薦這樣
function conjunctionJunctionWhatsYour() { //變量sNotGetCrazy 在這裏不可用 let( sNotGetCrazy = 'now' ) { //sNotGetCrazy is only visible in here }; //變量sNotGetCrazy 在這裏不可用};
綜述:主要的區別是 var 變量的範圍是整個封閉函數
js很容易在全局命名空間中建立變量,定義全局變量會污染共享的命名空間,而且可能致使意外的衝突,同時全局變量不利於模塊化,它會致使程序中獨立的組件沒必要要的耦合,在 code now and organize later 的時候可能比較方便,但優秀的程序員會不斷的留意程序的結構,持續的歸類相關的功能,以及分離沒必要要的組件,並將這些做爲編程過程當中的一部分。
js的全局命名空間也被暴露爲在程序全局做用域中能夠訪問的全局變量,這個對象做爲this的初始值,web瀏覽器中全局對象被綁定到全局的window變量,添加或者修改全局變量會自動的更新全局對象
這表明建立一個全局變量有兩種方法
1,在全局做用域中使用 var 聲明他
2,或者將其添加到全局對象中
var 聲明是變量的標準聲明
var 聲明的變量是永久性的,不能用delete運算符刪除
注意:
1,推薦使用var聲明的方式,這樣會比較清晰表達全局變量在程序中的影響
2,引用未綁定的變量會在運行時有錯誤,可是程序中給一個未綁定的變量賦值會簡單的建立一個新的全局變量
說道做用域,就要提到js中的做用域鏈的優先級:
嵌套函數的調用對象>調用對象>全局對象
看下面的例子(聲明:下面的例子摘自本人EverNote js筆記,應該是來源於互聯網,在此感謝做者給出的形象例子)
eg1. var scope="global"; function f(){ alert(scope); var scope="local"; alert(scope); } f(); 過程: 建立全局對象,搜索函數外的var聲明語句,在全局對象中建立scope屬性,scope=undefined 建立全局的執行環境,做用域鏈只有一個對象:全局對象 依次執行代碼: var scope="global"時,變量名解析開始,在全局對象屬性中查找scope屬性 把"global"賦給scope 遇到函數調用:建立調用對象 搜索函數中的var聲明語句和參數,在調用對象中建立scope的屬性,scope=undefined 建立函數執行環境,做用域鏈:調用對象>全局對象 依次執行代碼: alert(scope),查詢scope,變量名解析,先搜索調用對象,找到scope屬性,其值爲undefined,執行 var scope="local",查詢scope,變量名解析,先搜索調用對象,找到scope屬性,scope="local" alert(scope),查詢scope,變量名解析,先搜索調用對象,找到scope屬性,其值爲"local",執行 eg2. var scope="global"; function f(){ alert(scope); scope="local"; alert(scope); } f(); 過程: 建立全局對象,搜索函數外的var聲明語句,在全局對象中建立scope屬性,scope=undefined 建立全局的執行環境,做用域鏈只有一個對象:全局對象 依次執行代碼: var scope="global"時,變量名解析開始,在全局對象屬性中查找scope屬性 把"global"賦給scope 遇到函數調用:建立調用對象 搜索函數中的var聲明語句和參數,沒有找到var聲明語句 建立函數執行環境,做用域鏈:調用對象>全局對象 依次執行代碼: alert(scope),查詢scope,變量名解析,先搜索調用對象,沒找到scope屬性,再搜索全局對象,找到scope屬性,其值爲"global"執行 scope="local",查詢scope,變量名解析,先搜索調用對象,沒找到scope屬性,,再搜索全局對象,找到scope屬性,scope="local" alert(scope),查詢scope,變量名解析,先搜索調用對象,沒找到scope屬性,再搜索全局對象,找到scope屬性,其值爲"local",執行 eg3. scope1="global"; alert(scope1); function f(){ alert(scope2); scope2="local"; } f(); 過程: 建立全局對象,沒有找到var聲明語句,沒有自定義的全局對象屬性 建立全局的執行環境,做用域鏈只有一個對象:全局對象 依次執行代碼: scope1="global"時,變量名解析開始,做用域鏈是沒有找到scope1屬性,在全局對象屬性中建立scope1屬性,並賦值爲"global" alert(scope1)時,變量名解析開始,做用域鏈是找到scope1屬性,其值爲"global",執行 遇到函數調用:建立調用對象 搜索函數中的var聲明語句和參數,沒有找到var聲明語句 建立函數執行環境,做用域鏈:調用對象>全局對象 依次執行代碼: alert(scope2),查詢scope2,變量名解析,做用域鏈是沒有找到scope2屬性,報錯scope2 is not defined
說道做用域,就必需要提到「閉包」這個特性,閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即便已經離開了創造它的環境也不例外,這就叫閉包。
在 ECMAScript 中使用全局變量是一個簡單的閉包實例。
爲了更好的理解閉包,咱們要記住三點:
1,js容許引用在當前函數之外定義的變量
function makeSandwith(){ var magicIngredient = "peanut butter"; return function(filling){ return magicIngredient+" and "+filling; }('jelly')}//console: peanut butter and jelly
2,即便外部函數返回,js也容許當前函數引用在外部函數所定義的變量
function makeSandwith(){ var magicIngredient = "peanut butter"; return function(filling){ console.log(magicIngredient+" and "+filling); };}var res = makeSandwith();res('jelly')res('jelly')res('jelly')
上面代碼構造閉包的字面量語法叫作「函數表達式」,該函數是匿名的,咱們只須要它能產生一個新的函數值,而不打算在局部掉用它。
3,閉包能夠更新外部變量的值,實際上閉包存儲的是一個引用而不是副本
function box(){ var val = undefined; return{ set:function(newVal){val=newVal;}, get:function(){return val;}, type:function(){return typeof val;} }}var b = box();console.log(b.type());b.set('yeanzhi');console.log(b.get());console.log(b.type());console: undefined yeanzhi string
這個例子生成了三個閉包對象,分別是set,get,type,他們都共享val這個變量 下一篇介紹 運算符與操做符