es6 數值和函數的擴展

1.數值的擴展

(1)Number.EPSILON:ES6 在 Number 對象上,新增一個極小的常量,表示 1 與 大於 1 的最小浮點數之差。

(2)Math.trunc():去除一個數的小數部分,返回整數部分。

(3)Math.sign():用來判斷一個數是整數、負數還是零。

(4)Math.hypot():返回所有參數的平方和的平方根

(5)Math.cbrt():用於計算一個數的立方根。

(6)Math.clz32():將參數轉爲 32 位無符號整數的形式,然後返回這個 32 位值裏面有多少個前導 0

Math.clz32(0); //32 0的二進制形式全爲0,故前導有32個0
Math.clz32(1); //31 1的二進制形式爲 0b1,只佔1位,故32位之中有31個前導0
Math.clz32(0b01000000000000000000000000000000);  //1

(7)Math.imul():返回兩個數以32位帶符號整數形式相乘的結果,返回的也是一個32位帶符號整數。

(8)Math.fround():返回一個數的32位單精度浮點數形式。

(9)新增四個對數相關方法

Math.expm1(x):返回 e^x-1即 Math.exp(x)-1

Math.log1p(x):返回 1+x 的自然對數,即 Math.log(1+x),如果 x 小於 -1,則返回 NaN

Math.log10(x):返回以 10 爲底的 x 的對數,如果 x 小於 0,則返回 NaN

Math.log2(x):返回以 2 爲底的 x 的對數,如果 x 小於 -1,則返回 NaN

(10)** 指數運算符,特點是右結合,而不是左結合

2 ** 2  //4
2 ** 3  //8

let b = 4

b **= 3  // b = b*b*b

(11)BigInt 數據類型:BigInt 類型的數據必須添加後綴 n

(12)BigInt 對象 你不給一個

BigInt() 構造函數必須有參數,而且參數必須可以正常轉爲數值。參數若是小數也會報錯。

2.函數的擴展

(1)函數的 length 屬性,返回沒有指定默認值的參數個數(爲默認值前面的參數的個數)。不包括 rest 參數。

(2)rest 參數(...變量名):用於獲取函數的多餘參數,這樣就不用 arguments 對象了。這個參數搭配的是一個數組,該變量將多餘的參數放入數組中。在 rest 參數後面不能再有其它參數

function add(...values){
   let sum = 0;
   for (let val of values){
      sum += val;
   }
   return sum;
}

add(2,5,3);  //10

rest 參數代替 arguments 的例子

//arguments 寫法
function sortNumber(){
   return Array.prototype.slice.call(arguments).sort();
}

//rest 參數寫法
const sortNumbers = (...numbers) => numbers.sort();

(3)ES6 規定,只要函數參數使用了默認值,解構賦值或者擴展運算符,那麼函數內部就不能顯示設定爲嚴格模式。原因是函數體內的嚴格模式適用於函數體和函數參數,而函數執行的時候限制性參數再執行函數體。兩種方法可以規避這種限制

一、設定全局性的嚴格模式

'use strict';

function doSomething(a,b = a){
   ...
}

二、把函數包在一個無參數的立即執行函數裏面

const doSomething = (function(){
  'use strict'
  return function(value = 42){
    return value;
  }
}());

(4)name 屬性:返回函數的名字。

構造函數返回的函數實例,name 屬性的值爲 anonymous

(new Function).name; //anonymous

bind 返回的函數,name 屬性值前面會加上 bound 前綴

function foo(){};
foo.bind({}).name;  //"bound foo"

(function(){}).bind({}).name;//"bound"

(5)箭頭函數:使用 => 定義函數

var f = v => v;

//等同於
var f = function(v){
  return v;
};

若箭頭函數不需要參數或需要多個參數,就使用圓括號代表參數部分。

//例1
var f = () => 5;

//等同於
var f = function(){
   return 5;
}

//例2
var sum = (num1,num2) => num1 + num2;

//等同於
var sum = function(num1,num2){
  return num1 + num2;
};

若箭頭函數的代碼塊多於一條語句,就用花括號包起來,並用 return 語句返回。

var sum = (num1,num2) => {return num1 + num2};

由於花括號被解釋爲代碼塊,若箭頭函數返回一個對象,則必須在花括號外面再包上圓括號,否則會報錯。

let getTempItem = id => {id : id,name : "temp"};  //報錯

let getTempItem = id =>({id : id,name : "temp"}); //不報錯

遇到特殊情況會運行,但結果錯誤。

let foo = {} => {a:1};
foo();  //undefined

/* 因爲花括號爲代碼塊,所以執行了一行語句 a:1,這時 a 被解釋爲語句的標籤,因此,實際執行的語句是 1; 然後函數就結束了,沒有返回值
*/

若箭頭函數只有一行語句,且不需要返回值,就不用花括號了

let fn = () => void doesNotReturn();

箭頭函數可以與變量結合使用

const full = ({first,last}) => first + " " + last;

//等同於
function full(person){
  return person.first + "" + person.last;
} 

箭頭函數的用處

一:簡化回調函數

//正常函數寫法
[1,2,3].map(function(x){
  return x * x;
});

//箭頭函數寫法
[1,2,3].map(x => x * x);

二:rest 參數與箭頭函數結合的例子

//例1
const numbers = (...num) => num;

numbers(1,2,3,4,5);  //[1,2,3,4,5]

//例2
const headAndTail = (head,...tail) => [head,tail];

headAndTail(1,2,3,4,5);  //[1,[2,3,4,5]]

使用箭頭函數時需注意!

一:函數體內的 this 對象,就是定義時所在的對象,而不是使用時所在的對象。

二:不可以當做構造函數,也就是說不可以使用 new 命令,否則會拋出一個錯誤。

三:不可以使用 arguments 對象,該對象在函數體內不存在,若要使用,則用 rest 代替。

四:不可使用 yeild 命令,因爲箭頭函數不能用作 Generator 函數。

不適用箭頭函數的場合

一、定義對象的方法且該方法內部包括 this。

const cat = {
  lives:9,
  jumps:() => {
      return this.lives--;
  }
};

/*此時 this 指向全局變量,得不到預期的結果。這是因爲對象不構成單獨的作用域,使得 jumps 箭頭函數定義時的作用域就是全局作用域。
*/

二、需要動態 this 時,也不應使用箭頭函數

var button = document.getElementById("press");
button.addEventListener("click",() => {
   this.classList.toggle("on");
});

/*
點擊按鈕會報錯,因爲 button 的監聽函數是箭頭函數,導致裏面的 this 就是全局對象
*/

(6)尾調用:某個函數的最後一步是調用另一個函數

(7)尾遞歸:函數調用自身成爲遞歸,在最後一步調用自身成爲尾遞歸。

遞歸非常耗費內存,因爲要同時調用成千上百個調用幀,很容易發生“棧溢出”(stack overflow)錯誤。但對於尾遞歸來說,只存在一個調用幀,永遠不會發生棧溢出錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章