JavaScript基礎複習(四) 函數詳解

創建函數的方式

函數聲明和函數表達式
// 函數表達式   匿名函數 賦值給這個變量
var foo1 = function(...){}
// 函數表達式   命名
var foo2 = function acc(...){}
// 函數表達式 也就是立即執行函數
(function(){...})
// 函數表達式
setTimeout(funciton timer(){...},200)
// 函數聲明
function(){...}

函數聲明和函數表達式之間最重要的區別是它們的名稱標識符將會綁定在何處。函數聲明會綁定在自身的作用域中,而函數表達式會綁定在表達式自身的函數中,而不是所在作用域中。 也就是,看function出現在哪裏,如果出現在最開始,那就是函數聲明,其他都是函數表達式。

// 函數表達式和函數聲明

// 函數表達式
// console.log(boo);  // undefined
// boo(); // boo is not a function
var boo = function(){
    console.log('這是一個匿名函數賦值變量,只能在賦值之後使用,在之前調用會報錯')
}
console.log(boo);  // 輸出函數內容
boo(); // 這是一個匿名函數賦值變量,只能在賦值之後使用,在之前調用會報錯

//命名函數賦值變量
// console.log(loo); // loo is not a function
console.log(coo);  // undefined
// loo();  // loo is not defined
// coo();   // coo is not a function
var coo = function loo(){
    loo();   //函數名在函數內部總是 可見的,正常運行,前提是,外部沒有調用 coo 
    console.log('這是一個命名函數賦值變量,所以是調用loo還是coo呢')
}
// console.log(loo);  // loo is not defined
console.log(coo);  //  輸出函數內容
// loo();   //loo is not defined
// coo();  // 這是函數聲明,在執行前被 解析,存在當前上下文的所有地方,可以任意地方調用



// 函數聲明
function aoo(){
    console.log('這是函數聲明,在執行前被 解析,存在當前上下文的所有地方,可以任意地方調用')
}
console.log(aoo)
aoo();

箭頭函數
// 沒有return
acc = () => {...}

特點:

  • 沒有 this、super、arguments 和 new.target 綁定 箭頭函數內部的這些值直接取自定義時的外圍非箭頭函數
  • 不能通過 new 關鍵字調用 箭頭函數沒有 [[Construct]] 方法,所以不能被用作構造函數,如果通過 new 關鍵字調用箭頭函數,程序會拋出錯誤。
  • 沒有原型 由於不可以通過 new 關鍵字調用箭頭函數,因而沒有構建原型的需求,所以箭頭函數不存在 prototype 這個屬性。
  • 不可以改變 this 的綁定 函數內部的 this 值不可被改變,在函數聲明週期內始終保持一致。
  • 不支持 arguments 對象 箭頭函數沒有 arguments 綁定,所以你必須通過命名參數和不定參數這兩種形式訪問函數的參數。
  • 不支持重複的命名參數 無論是在嚴格還是非嚴格模式下,箭頭函數都不支持重複的命名參數;而在傳統函數的規定中,只有在嚴格模式下纔不能有重複的命名參數。

由於沒有 this 的綁定,箭頭函數的 this 值不受 call()、apply()、bind() 方法的影響。

箭頭函數完全修復了this的指向,this總是指向詞法作用域,也就是外層調用者obj

構造函數與類

在 ES6 Class 特性出現以前,我們經常使用 構造函數來模擬類的特性。思路基本都是:首先創建一個構造函數,然後定義另一個方法並複製給構造函數的原型。

function Person(name) {
    this.name = name
}
Person.prototype.sayName = function() {
    console.log(this.name)
}
 
const person = new Person('Tumars')
person.sayName()  // "Tumars"
 
console.log(person instance Person)  // true
console.log(person instance Object) // true

上面代碼中 Person 是一個構造函數,其執行後創建了一個名爲 name 的屬性;給 Person 的原型添加一個 sayName() 方法,所以 Person 對象的所有實例都會共享這個方法。由於存在原型繼承的特性,person 對象是 Person 的實例,也是 Object 的實例。

通過構造函數創建的普通函數對象,擁有原型。

ES6 中的類是對構造函數寫法的一種語法糖,它簡化了構造函數的寫法。

class PersonCLass {
    constructor(name) {
        this.name = name
    }
 
    // 等價於 Person.prototype.sayName()
    sayName() {
        console.log(this.name)
    }
}
 
const person = new Person('Tumars')
person.sayName()  // "Tumars"
 
console.log(person instance PersonClass)  // true
console.log(person instance Object) // true

通過類聲明語法定義 PersonClass 的行爲與之前創建 Person 構造函數的過程相似,只是這裏直接在類中通過特殊的 constructor 方法名來定義構造函數,且由於這種類使用簡介語法拉定義方法,因而不需要添加 function 關鍵字。

實例方法

apply()、call()

使用 apply 與 call 調用函數被稱爲函數應用。這兩個方法的用途都是在特定的作用域中調用函數,實際上等於設置函數體內 this 對象的值。

  • apply() 方法調用一個函數, 其具有一個指定的this值,以及作爲一個數組(或類似數組的對象)提供的參數。
  • call() 方法調用一個函數, 其具有一個指定的this值和分別地提供的參數(參數的列表)。

bind()

bind()方法會創建一個新的函數, 當被調用時,將其this關鍵字設置爲提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。

函數去抖與函數節流

函數式編程

聲明式的,不可變的,沒有副作用的是函數式編程的三大護法

  • 純函數

    對於相同的輸入,永遠會得到相同的輸出,而且沒有任何可觀察的副作用,也不依賴外部環境的狀態的函數,叫做純函數。

  • 函數的柯里化

    傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。

  • 高階函數

    高階函數,就是把函數當參數,把傳入的函數做一個封裝,然後返回這個封裝函數,達到更高程度的抽象。

var checkage = min => (age => age > min);
var checkage18 = checkage(18); // 先將18作爲參數,去調用此函數,返回一個函數age => age > 18;
checkage18(20);// 第二步,上面返回的函數去處理剩下的參數,即 20 => 20 > 18; return true;

事實上柯里化是一種“預加載”函數的方法,通過傳遞較少的參數,得到一個已經記住了這些參數的新函數,某種意義上講,這是一種對參數的“緩存”,是一種非常高效的編寫函數的方法。

導圖
image

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