講義內容:JS 誕生的背景、基本類型、運算符java
如下內容只涉及 ES5 標準,ES6 增長的新內容能夠在網上查找到。node
上世紀 90 年代網景公司開發的瀏覽器獨步天下typescript
一個叫作 Brendan Eich 的工程師受命於開發一款腳本語言,來加強瀏覽器的功能。編程
這名工程師花費了 10 天時間設計出了第一個版本,名叫 LiveScript。數組
後來由於當時 Java 正紅,公司將其更名爲 JavaScript,因此 JS 和 Java 其實沒有什麼關係。瀏覽器
這名工程師在設計語言之初有幾個目標閉包
後來 JS 由於市場認同,戰勝了 VBScript,Java plugin 等一系列加強瀏覽器的方案,成了事實標準。函數式編程
網景公司倒閉以後,JS 的標準制定由 ECMA(歐洲電腦製造商協會)制定,因此又叫作 ECMAScript, 新的標準叫作 ES六、ES七、ES2018 … 每一年會收集各類語言規範建議,經過 草案、stage一、stage2 等幾個階段,並在瀏覽器中有實現後會成爲正式標準。函數
因此 JS 具備如下特色:this
會在項目裏使用還在草案階段的新語法
變種、超集、子集 不少(coffee script, typescript, Action Script, flow, AssembleScript)
JS 中的基本類型有如下幾種:
另外有三種引用類型:
和 Java 同樣,全部類型都是基於 Object(除了 undefined ?)
經過 「var」關鍵字聲明一個變量,方法和大多數語言同樣。
JS 是動態語言,變量不用區分類型,不一樣類型之間的變量能夠相互賦值。
var foo = 1; var bar; var a, b, c; bar = foo = 「abcd」 undefined 和 null
當一個值沒有初始值的時候,默認值爲 undefined。
undefined 在 JS 中是個語言設計的缺陷例子。
undefined 的行爲在大多數狀況下和 null 同樣,都是不可訪問的值,可是在 typeof 的時候結果不一樣
var und; var nl = null; typeof und === ’undefined’ typeof nl == ‘object’
Boolean, Number,String 的行爲和大多數語言同樣。
能夠直接聲明也能夠經過構造函數、工廠模式聲明,三者沒什麼區別。
var a = 123 var a = new Number(123) var a = Number(123)
在 JS 中 數字的取值範圍是 -253 - 1 到 253 - 1,範圍小於 long 型,而且計算時有精度問題
1.2 / 0.2 // 5.999999999999999
聲明數字的方式和其它語言相似,科學計數法、八進制、十六進制
var a = 1e3 // 1000 var a = 0o12 // 10 var a = 0xa // 10
經過 「toString」方法能夠轉換成字符串,並設置進制
var a = 1000 a.toString(10) // 「1000」 a.toString(8) // 「1750」 a.toString(16) // 「3e8」
在 JS 中,有兩個特殊的數字,NaN 和 Infinity。
當字符串或者其餘類型轉換成數字失敗的時候,就會返回 NaN,可是 NaN 的類型依然是 number。
NaN 和任何數字計算後,結果都是 NaN。
當數字除以 0 的時候,就會返回 Infinity。
Number(undefined) // NaN Number(null) // 我也很費解,爲何 null 轉換成數字就是 0 // 0 Number("asdf") // NaN 10 / 0 //Infinity
在 JS 中字符串是可變長,並且能夠經過 「+」 操做符作拼接。
字符串在內容中應該是雙字節儲存,能夠經過索引訪問每一個字符,而不是每一個 byte。
在瀏覽器中編碼格式根據網頁的編碼格式而設置(在 node 中默認是 UTF8?)
在 JS 中,聲明一個字符串經過單引號或者雙引號均可以,兩者沒有區別。一般習慣是經過單引號訪問,由於能夠少按一個 shift。
var a = ‘123’ var b = 「123」 a == b a[0] // 經過索引訪問的結果仍然是個字符串 // 「1」
函數在 JS 中是一等公民,能夠賦值給變量,有兩種聲明方式
function plus(a, b) { return a + b} var plus = function(a, b) { return a + b }
第二種方法實際上是將一個「匿名函數」複製給了變量 plus。
這兩種方式在使用上沒太大區別,除了在「聲明前置」的場景下會有點區別
匿名函數還有一種方法叫作「當即執行函數」。
(function(a, b){ return a + b })(10, 20) // 30
函數只會將 return 聲明的表達式的值返回出去,在函數沒有聲明 return 的時候,默認返回 undefined
function plus (a, b) { a + b } plus(1, 2) // undefined
函數和做用域
函數和變量同樣,能夠在任何地方聲明、使用,
每一個函數獨立出了一個做用域,做用域能夠互相嵌套。
函數做爲一個變量,自己也在父做用域下
function foo(b) { var a = 10 // 這裏屬於 foo 的做用域,內部有 bar, b, a 三個變量 function bar() { var c = 20; return a + b + c // 這裏屬於 bar 的做用域,由於在 foo 以內,因此能夠訪問 a 和 b } // 這裏不能訪問 c return bar(); }
因爲 JS 在設計的時候,怕用戶不理解變量須要先聲明再使用,因此對變量會有「聲明前置」,幫助你們提早聲明所須要的變量。
下面咱們用當即執行函數建立一個閉包來解釋什麼叫「聲明前置」
(function() { console.log(fn, foo); function fn(a, b){ return a + b }; var foo = 1234; console.log(fn, foo); })() // function (a, b){ return a + b } undefined // function (a, b){ return a + b } 1234
上面的代碼至關於:
(function() { function fn(a, b){ return a + b }; var foo; console.log(fn, foo);• foo = 1234; console.log(fn, foo); })()
若是咱們用匿名函數賦值給一個變量,那麼會有下面效果:
(function() { console.log(fn, foo); var fn = function(a, b){ return a + b }; var foo = 1234; console.log(fn, foo); })() // undefined undefined // function (a, b){ return a + b } 1234
上面的代碼至關於:
(function() { var fn, foo; console.log(fn, foo); fn = function(a, b) { return a + b}; foo = 1234; console.log(fn, foo); })()
在 JS 中數組是可變的,並且數組內能夠聽任何值。
數組的長度是最後一個元素的索引加一。
若是訪問沒有設置的元素,將會返回 unfined
var array = []; array[0] = 1; array[2] = 「1234」; array[4] = function(){}; // [1, undefined, 「1234」, function(){}] array[1] // undefined
js 數組中自帶了不少方法,方便咱們對數組作操做,好比說 map, reduce 等等
[1, 2, 3].map(function(d) { return d + 1 }) // [2, 3, 4] [1, 2, 3].reduce(function(r, d) { return r + d }, 0) // 6
若是想要刪除數組中的某個元素的話,咱們能夠用 delete 關鍵詞,或者直接將索引的位置設置成 undefined
var array = [1, 2, 3] delete array[1] // [1, undefined, 3]
若是咱們須要刪除數組中某個元素,而且縮短數組長度的話,就須要用到 splice。
var array = [1, 2, 3] array.splice(1, 1) console.log(array) // [1, 3]
一些經常使用的數組方法還有 slice, forEach, find, every, includes 等等
和 java 同樣,對象(Object) 是全部類型的基類。它相似 JSON 裏的鍵值對結構體,能夠動態的掛載任何屬性。
聲明的方法有兩種,{} 和 new
var a = {} var b = new Object() a.num = 1 a.str = "1234" console.log(a) // { num: 1, str: "1234"}
對象(Object)有點相似 Java 裏的 HashMap,但 Key 只能是字符串。能夠經過相似數組索引的方式來訪問對象上的鍵。
這種方法和點操做符是同樣的效果,當鍵名由一些特殊的字符組成的時候,咱們能夠經過索引方式訪問。
var obj = {value: 1234} console.log(obj["value"]) // 1234
這樣聲明或者訪問會報錯:
var obj = { some-value: 1234 } obj.some-value
咱們須要讓編譯器知道 some-value 是一個鍵名,因此須要將它們用引號括起來
var obj = { "some-value": 1234 } obj["some-value"]
當一個對象中掛載了一個函數,在函數中能夠經過 this 來訪問對象內的其餘屬性,this 也能夠理解爲「執行上下文」
function fn () { console.log(this.value) } var obj = { fn: fn, value: 1234 } obj.fn() // 此時 fn 的執行上下文就是 obj // 1234 var otherObj = { fn: fn, value: "abcd"} otherObj.fn() // 此時 fn 的執行上下文就是 otherObj // "abcd"
因爲函數和數組是全部類型的基類,因此能夠像對象同樣隨意的擴展屬性。
可是字面量(如數字、布爾值、字符串、null、undefined) 是不能隨意擴展的。
function plus(a, b) { return a + b} plus.value = 1234 plus(12, plus.value) // 1246 var array = [] array.value = 1234 console.log(array.value) // 1234 var a = true; a.value = 1234 console.log(a.value) // undefined
JS 的運算符和其餘語言基本相似,就+-*%/這些,外加一些二進制操做符。
但由於 JS 弱類型的特性,有些場景是其餘語言沒有的,好比一個數字加一個字符串,結果是什麼?
1+"2" // "12"
這種場景還能夠理解,數字和字符串相加的時候,數字經過調用 toString 被轉換成了字符串。
1 + {} // "1[object Object]"
數字和對象相加的時候,對象和數字都調用了 toString,被轉換成了字符串
{} + [] // 0
可是空對象和空數組相加結果倒是 0,我也不知道爲何
var obj = {} if (obj) console.log("obj is true") // "obj is true" obj == true // false
上面這個例子中,obj 是個空對象,在 if 條件判斷中被看成真值,可是和 true 對比的時候卻返回 false。
JS 的隱式轉換規則很詭異,不少都是爲了兼容早期版本中錯誤的實現,這裏不必細究轉換規則是什麼。
咱們只須要記住之後用嚴格相等符(===)做對比,避免不一樣類型的變量相互運算。
"1" == 1 // true "1" === 1 // false
JS 的循環和其它相似,也都是 for, do..while 這種寫法。
可是,咱們通常不用 for 做循環,而是用數組方法 forEach,map(由於 for 寫起來很麻煩,並且還須要單獨聲明一個變量)
[1, 2, 3].forEach(function(value) { return value + 1; }) // [2, 3, 4]
另外還能夠經過 for...in 來遍歷一個對象
var obj = {a:1, b:2, c: 3} for (var key in obj) { console.log(key) } // "a" // "b" // "c"
但咱們通常也不這麼用,而是用 Object.keys 取得包含對象全部鍵的數組
var obj = {a:1, b:2, c: 3} Object.keys(obj) // ["a", "b", "c"] Object.keys(obj).forEach(console.log) // "a" // "b" // "c"
第一題:JS 的運用領域都有哪些,做爲弱類型的語言執行效率如何,爲何?
第二題:typeof 關鍵字的返回值有幾種結果?
第三題:下面兩種寫法有什麼區別
{ 0: "a", 1: "b", 2: "c" } ["a","b","c"]
第四題:下面代碼的運行時會不會報錯,this 指向哪裏?
function fn () { console.log(this.value) } fn()
第五題:聲明的變量是如何被回收的