標籤:更改 綁定 接收 read javascrip 首碼 運算 bind 學習
函數
ES6文法支援rest參數
rest參數只能定義在參數最後面,用...標識。如果傳入的參數連正常定義的參數都沒有填滿,則rest參數會接收一個空數組。
變數範圍
用var聲明的變數實際上都是有範圍的,內建函式可以訪問外部函數定義的變數,尋找變數時都是從自身函數定義開始,從內向外尋找。如果內建函式定義了與外部函數重名的變數,則內建函式的變數將屏蔽外部函數的變數。
變數提升
JS函數會先掃描整個函數體的語句把所有聲明的變數提升到函數頂部。因此建議在函數內部定義變數時請嚴格遵守“函數內部首先聲明所有變數”規則。
全域範圍
不在任何函數內定義的變數都具有全域範圍,預設全域對象window
namespace命名空間
將所有的變數和函數全部綁定在一個全域變數中
局部範圍
ES5沒有塊級範圍,因此在ES6中,引入了let關鍵字。用let代替var可以聲明一個塊級範圍變數
常量
在ES6中引入了const關鍵字來定義常量,const和let都具有塊級範圍
this
在一個獨立的函數範圍中,如果this沒有指定某個對象。那麼在strict 模式下this指向undefined,在非strict 模式下this指向window
如果更改this的指向呢?
1. apply方法可以指定函數的this指向,接收兩個參數,第一個是this需要綁定的變數,第二個表示函數本身的參數數組
2. call方法會把參數按照順序打包成Array進行傳入
普通函數的調用通常是把this綁定為null
var count = 0;var oldParseInt = parseInt;window.parseInt = function(){ count+=1; return oldParseInt.apply(null, arguments);};
閉包
在函數內部定義的函數能夠訪問外部函數的局部變數的特性被稱為閉包
經典大坑:返回函數不要引用任何迴圈變數或者後續會發生變化的變數
function count(){ var arr=[]; for(var i=1; i<=3; i++){ arr.push(function(){ return i*i; }); } return arr;}var results = count();var f1= results[0];var f2= results[1];var f3= results[2];f1();f2();f3();// 這三個函數的傳回值都是16
ES6對函數的擴充1. 函數參數的預設值
ES6可以給函數的參數指定預設值,可以避免在ES5中使用 || 的文法實現預設值
但是這樣有一個缺陷,或語句邏輯運算式的第一個參數的布爾值如果為false那麼也會使用預設值。 比如傳入一個Null 字元串,轉換為布爾值就是false
所以一般都要先判斷該變數是否有值
// ES5 文法function log(x, y){ if(typeof y == ‘undefined‘){ y = ‘world‘; }}function log(x, y){ if(arguments.length == 1){ y = ‘world‘; }}
在ES6中,直接在參數定義後面使用等號進行預設值賦值
function log(x, y = "world"){ console.log(x, y);}log("hello"); // hello worldlog("hello", "es6"); // hello es6log("hello", ""); // hello
參數變數是預設聲明的,所以不能在函數體內再次使用 let 或者 const 聲明。
小坑:
如果函數參數是一個對象,但是並沒有給整個對象賦予預設值時。那麼調用函數時如果不傳入參數,則會報錯。
最後時刻警惕下列情況
function m1({x = 0 , y = 0} = {}){ return [x, y];}function m2({x, y} = {x: 0, y: 0}){ return [x, y];}
參數預設值的位置必須是最後一個函數參數,如果不是最後一個參數,則有預設值的參數需要顯示傳入undefined才能跳過該參數,而null是無法跳過的。這一點可以參考對象的解構賦值
2. 函數的length屬性
函數的length屬性 = 函數的參數個數 - 指定了預設值的參數個數
rest參數也不會計入length屬性
3. 範圍
如果參數預設值是一個變數,則該變數所處的範圍與其他變數的範圍規則是一樣的。先是當前函數範圍,再是全域範圍。
如果函數調用時預設值變數尚未在函數內部產生時,那麼該變數會指向全域範圍。
如果函數調用時預設值是一個函數,那麼函數範圍是聲明時所在的範圍,也就是全域範圍。
4. rest參數
ES6引入了Rest參數,Rest參數必須是最後一個參數,也就是得放在普通參數和預設值參數之後。
Rest參數可以代替arguments變數
const sortNumbers = () => [].prototype.slice.call(arguments).sort();const sortNumbers = (...numbers) => numbers.sort();
Rest參數變數代表一個數組,所以數組方法都可以用在這個變數上。
function push(array, ...items){ items.forEach( (item) => { array.push(item); });}var arr = [];push(arr, 1, 2, 3, 4);
5. spread擴充運算子
可以將一個數群組轉換為用逗號分隔的參數序列,用途:
1. 替代數組的apply方法
2. 合并數組
3. 與解析賦值結合
4. 函數傳回值解析
5. 字串解析
6. 類數組對象的解析
6. 函數的name屬性
ES6才將name屬性寫進標準中,但是很多瀏覽器都已經實現了這個功能
另外ES6規定了匿名函數也是有name屬性的,也會返回實際的函數名。而在大部分瀏覽器中則依然返回Null 字元串
Function建構函式返回的函數執行個體,name屬性 = ‘anonymous‘
函數通過bind()方法進行this綁定後,返回的函數的name屬性會在原先的name屬性值上添加"bound "首碼
7. 箭頭函數 (重點中的重點)
1. 如果函數不需要參數或者需要多個參數,需要使用()將參數部分包圍。 僅僅對於只有一個參數的函數可以省略掉()
2. 如果函數體多於一條語句,需要使用{}將函數體包圍。並使用return 語句返回。 對於一條語句可以省略{}
3. 如果函數返回的是對象,那麼就需要在{}外面套上()
4. 函數體內的this對象已經改變了,表示的是函數定義時所在的對象。而不是原來的使用時所在的對象。
5. 箭頭函數不能作為建構函式進行使用
6. 箭頭函數中不能使用arguments對象
7. 箭頭函數中不能使用yield語句
8. 箭頭函數實質上是沒有this的,同時arguments, super, new.target也都不存在
[JavaScript文法學習]全面介紹函數