最近在刷廖雪峰的JS教程,把裡面的自己不太清楚的東西在刷一遍。
教程網址:www.liaoxuefeng.com/wiki/001434…
函式的定義和呼叫:
- 如果沒有
return
語句,函式執行完畢後也會返回結果,只是結果為undefined
。 - JavaScript允許傳入任意引數,即使函式內部不需要這些引數,也不影響呼叫。
- JavaScript還有一個免費贈送的關鍵字
arguments
,它只在函式內部起作用,並且永遠指向當前函式的呼叫者傳入的所有引數。arguments
類似Array
但它不是一個Array
- 利用
arguments
即使函式不定義任何引數,還是可以拿到引數的值。function abs() { if (arguments.length === 0) { return 0; } var x = arguments[0]; return x >= 0 ? x : -x; } abs(); // 0 abs(10); // 10 abs(-9); // 9複製程式碼
- ES6引入了新的
rest
引數,他可以獲得額外的rest
引數,rest
引數只能寫在最後,前面用...標識,從執行結果可知,傳入的引數先繫結a、b,多餘的引數以陣列形式交給變數rest
,所以,不再需要arguments我們就獲取了全部引數。(如果傳入的引數連正常定義的引數都沒填滿,也不要緊,rest引數會接收一個空陣列(注意不是undefined))function foo(a, b, ...rest) { console.log('a = ' + a); console.log('b = ' + b); console.log(rest); } foo(1, 2, 3, 4, 5); // 結果: // a = 1 // b = 2 // Array [ 3, 4, 5 ] foo(1); // 結果: // a = 1 // b = undefined // Array []複製程式碼
return
語句必須在一行上,如果必須為多行返回,需要在retrun
後緊跟{
,正確的多行寫法如下:function foo() { return { // 這裡不會自動加分號,因為{表示語句尚未結束 name: 'foo' }; }複製程式碼
變數作用域:
- 如果用
var
在函式體內宣告變數,該變數作用域為整個函式;因為這個原因,在不同函式內部用var申明的同名變數互相獨立,互不影響。 - 由於函式可以相互巢狀,內部函式可以訪問外部函式定義的變數,但是如果內部和外部都定義了同名變數怎麼辦了?JS函式查詢變數會從自身定義函式開始,也就是從’內’向’外’,順著作用域鏈查詢,如果內部函式已經定義了,則會’遮蔽’掉外部函式變數。
- JS函式的
var
定義有個特點,它會先掃描整個函式體的語句,把所有var
申明的變數“提升”到函式頂部,所以定義變數時,我們應該嚴格遵守在函式內部先宣告的規則。 - JavaScript預設有一個全域性物件
window
,全域性作用域的變數實際上被繫結到window
的一個屬性上了。 - 為了防止造成命名衝突,比較好的方法是把自己的所有變數和函式,都繫結到一個全域性變數中:
// 唯一的全域性變數MYAPP: var MYAPP = {}; // 其他變數: MYAPP.name = 'myapp'; MYAPP.version = 1.0; // 其他函式: MYAPP.foo = function () { return 'foo'; };複製程式碼
- 在for迴圈是無法定義具有區域性作用域的的變數的。在ES6中可以使用
let
替代var
可以申明一個塊級作用域的變數。 - 對於常量的定義,以前都是使用全部大寫來規定,現在ES6總可以使用關鍵字
const
來定義常量,const
與let
都具有塊級作用域,並且const
定義以後無法修改。 - 補充說明一下
let
和const
的特點,不存在變數提升、會造成暫時性死區、不允許重複定義。
方法:
在一個物件中繫結函式,稱為這個物件的方法。這裡要介紹一個很坑爹的概念,就是this
的指向問題。
那麼對於不同的呼叫,這個this
的指向分別是什麼了??
答:this
的指向在函式定義的時候是確定不了的,只有函式執行的時候才能確定this
到底指向誰,實際上this
的最終指向的是那個呼叫它的物件。
在《javascript語言精髓》中大概概括了4種呼叫方式:
1. 方法呼叫模式
2. 函式呼叫模式
3. 構造器呼叫模式
4. apply/call呼叫模式複製程式碼
特別補充:
- 在構造器呼叫時,如果加入了
return
並且return
了一個物件,this
會指向這個return
的物件。 - 嚴格模式下在函式內部定義的函式,
this
指向undefined
(在非strict模式下,它指向全域性物件window
)
那麼有沒有辦法去控制this
的指向了?
有的,可以使用函式本身的apply
方法,它接收兩個引數,第一個引數就是需要繫結的this
變數,第二個引數是Array
,表示函式本身的引數。另一個與apply()
類似的方法是call()
,唯一區別是:
apply()
把引數打包成Array
再傳入;call()
把引數按順序傳入。
另外ES5還加入了一個bind()
方法,它會建立一個函式的例項,其this值會被繫結到傳給bind()
函式的值。
利用apply()
,我們還可以動態改變函式的行為。
JavaScript的所有物件都是動態的,即使內建的函式,我們也可以重新指向新的函式。
高階函式:
- 一個函式接收另一個函式作為引數,這種函式就稱之為高階函式。
forEach
方法,是最基本的方法,就是遍歷與迴圈,預設有3個傳參:分別是遍歷的陣列內容item、陣列索引index、和當前遍歷陣列Array。另外,除去第一個必須的回撥函式引數,還可以接受一個上下文引數(改變回撥函式的this
指向);並且forEach
不會遍歷空元素。map
方法,基本用法與forEach
一致,但是不同的,它會返回一個新的陣列,所以在callback
需要有return
值,如果沒有,會返回undefined
。(從字面理解,map就是對映的意思)filter
方法,用法和map
很相似,從字面理解,就是過濾、篩選的意思。但是函式的callback
需要返回布林值true
或false
,並且返回值只需要為弱等==即可。some
方法,對陣列中每一項執行指定函式,如果該函式對任一項返回true
,則返回true
。(一旦遇到true
,就會中斷迴圈,返回true,類似於||判斷)every
方法,對陣列中的每一項執行給定函式,如果該函式對每一項返回true
,則返回true
。(一旦遇到false
,就會中斷迴圈,返回false
,類似於&&
判斷)sort
方法,預設把所有元素先轉換為String
再進行ASCII碼排序,所以這個很坑爹。要想正確的排序,需要新增一個函式。sort
方法,可以接受一個回撥函式,預設有兩個傳參:分別是比較的陣列項。
閉包(還要在研究一下,以後補充吧):
「閉包」,是指那些能夠訪問獨立(自由)變數的函式(變數在本地使用,但定義在一個封閉的作用域中)。換句話說,這些函式可以“記憶”它被建立時候的環境。特性:
- 函式巢狀函式
- 函式內部可以引用外部的引數和變數
- 引數和變數不會被垃圾回收機制回收
箭頭函式:
- 箭頭函式使得表達更加簡潔。
- 函式體內的
this
物件,就是定義時所在的物件,而不是使用時所在的物件。 - 不可以當作建構函式,也就是說,不可以使用
new
命令,否則會丟擲一個錯誤。 - 不可以使用
arguments
物件,該物件在函式體內不存在。如果要用,可以用Rest
引數代替。 - 不可以使用
yield
命令,因此箭頭函式不能用作Generator
函式。
Generator:
Generator
函式是協程在 ES6 的實現,最大特點就是可以交出函式的執行權(即暫停執行)。next
法返回值的value
屬性,是Generator
函式向外輸出資料;next方法還可以接受引數,向Generator
函式體內輸入資料。Generator
函式內部還可以部署錯誤處理程式碼,捕獲函式體外丟擲的錯誤。
有錯誤希望指出,一定會及時修改!