国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript深入淺出第2課:函數是一等公民是什么意思呢?

wmui / 2219人閱讀

摘要:函數是一等公民,是什么意思呢我來與大家探討一下,拋磚引玉。對于來說,函數可以賦值給變量,也可以作為函數參數,還可以作為函數返回值,因此中函數是一等公民。也就是說,函數為第一公民是函數式編程的必要條件。

摘要: 聽起來很炫酷的一等公民是啥?

《JavaScript深入淺出》系列

JavaScript深入淺出第1課:箭頭函數中的this究竟是什么鬼?

JavaScript深入淺出第2課:函數是一等公民是什么意思呢?

看到一篇講JavaScript歷史的文章里面提到:JavaScript借鑒Scheme語言,將函數提升到"一等公民"(first class citizen)的地位

一等公民這個名字聽起來很高大上,但是也相當晦澀,這個與翻譯也沒什么關系,因為first class citizen很多人包括我也不知所云。

JavaScript函數是一等公民,是什么意思呢?我來與大家探討一下,拋磚引玉。

一等公民的定義

根據維基百科,編程語言中一等公民的概念是由英國計算機學家Christopher Strachey提出來的,時間則早在上個世紀60年代,那個時候還沒有個人電腦,沒有互聯網,沒有瀏覽器,也沒有JavaScript。

大概很多人和我一樣,沒聽說過Christopher Strachey,并且他也只是提出了一等公民的概念,沒有給出嚴格的定義。

關于一等公民,我找到一個權威的定義,來自于一本書《Programming Language Pragmatics》,這本書是很多大學的程序語言設計的教材。

In general, a value in a programming language is said to have ?rst-class status if it can be passed as a parameter, returned from a subroutine, or assigned into a variable.

也就是說,在編程語言中,一等公民可以作為函數參數,可以作為函數返回值,也可以賦值給變量

例如,字符串在幾乎所有編程語言中都是一等公民,字符串可以做為函數參數,字符串可以作為函數返回值,字符串也可以賦值給變量。

對于各種編程語言來說,函數就不一定是一等公民了,比如Java 8之前的版本。

對于JavaScript來說,函數可以賦值給變量,也可以作為函數參數,還可以作為函數返回值,因此JavaScript中函數是一等公民。

函數作為函數參數

回調函數(callback)是JavaScript異步編程的基礎,其實就是把函數作為函數參數。例如,大家常用的setTimeout函數的第一個參數就是函數:

setTimeout(function() {
    console.log("Hello, Fundebug!");
}, 1000);

JavaScript函數作為函數參數,或者說回調函數,作為實現異步的一種方式,大家都寫得多了,其實它還有其他應用場景。

Array.prototype.sort()在對一些復雜數據結構進行排序時,可以使用自定義的比較函數作為參數:

var employees = [
    { name: "Liu", age: 21 },
    { name: "Zhang", age: 37 },
    { name: "Wang", age: 45 },
    { name: "Li", age: 30 },
    { name: "zan", age: 55 },
    { name: "Xi", age: 37 }
];

// 員工按照年齡排序
employees.sort(function(a, b) {
    return a.age - b.age;
});

// 員工按照名字排序
employees.sort(function(a, b) {
    var nameA = a.name;
    var nameB = b.name;
    if (nameA < nameB) {
        return -1;
    }
    if (nameA > nameB) {
        return 1;
    }
    return 0;
});

這樣寫看起來沒什么大不了的,但是對于JavaScript引擎來說就省事多了,因為它不需要為每一種數據類型去實現一個排序API,它只需要實現一個排序API就夠了,至于數組元素大小怎么比較,交給用戶去定義,用戶如果非得說2大于1,那也不是不可以。

換句話說,如果Array.prototype.sort()只能實現簡單數據(比如Number與String)的排序的話,那它就太弱了,正因為可以使用函數作為參數,使它的功能強大了很多。

順便提一下,實現一個Array.prototype.sort(),可不是什么簡單的事情,大家可以看看V8是怎樣實現數組排序的。

將函數賦值給變量

JavaScript是可以定義匿名函數的,當我們定義有名字的函數時,通常是這樣寫的:

function hello() {
    console.log("Hello, Fundebug!");
}

當然,也可以將函數賦值給變量:

var hello = function() {
    console.log("Hello, Fundebug!");
};

console.log(typeof hello); // 打印 function

可知,hello變量的類型是"function"。

在其他的一些First-class function的定義中,還要求函數可以保存到其他數據結構,比如數組和對象中,這一點JavaScript也是支持的。

In?computer science, a?programming language?is said to have?first-class functions?if it treats?functions?as?first-class citizens. This means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.

函數可以保存到Object中,就意味著函數成為了Object的方法。我在《JavaScript深入淺出第1課:箭頭函數中的this究竟是什么鬼?》中提過,當函數作為Object的方法被調用時,它的this值就是該Object,這1點與Java等面向對象語言是一致的。因此JavaScript在沒有Class之前,就在一定程度上是支持面向對象編程的,當然比較弱。

var person = {
    name: "Wang Lei",
    age: 40,
    greeting: function() {
        console.log(`Hello! My Name is ${this.name}.`);
    }
};

console.log(person.age); // 打印 40
person.greeting(); // 打印 Hello! My Name is Wang Lei.
函數作為函數返回值

通常來講,函數的返回值比較簡單,比如數字、字符串、布爾值或者Object。由于JavaScript函數是第一公民,因此我們也可以在函數中返回函數。

function sayHello(message) {
    return function() {
        console.log(`Hello, ${message}`);
    };
}

var sayHelloToFundebug = sayHello("Fundebug!");
var sayHelloToGoogle = sayHello("Google!");

sayHelloToFundebug(); // 打印Hello, Fundebug!
sayHelloToGoogle(); // 打印Hello, Google!

當我們調用sayHello函數時,它返回值sayHelloToFundebug實際是一個函數,我們需要調用所返回的sayHelloToFundebug函數,它才會執行,打印對應的信息:"Hello, Fundebug!"。

我猜這個地方有人會抬杠,因為示例代碼沒有必要這么寫,因為有更簡單的寫法:

function sayHello(message) {
    console.log(`Hello, ${message}`);
}

sayHello("Fundebug!"); // 打印Hello, Fundebug!
sayHello("Google!"); // 打印Hello, Google!

但是這只是一個簡單的示例,在一些復雜的實際場景中,在函數返回函數還是很有用的。下面給大家一個簡單的示例。

我們Fundebug在微信小程序BUG監控插件的時候,把不同API的定義拆分在不同的文件,但是這些API需要共享一些全局屬性,比如用戶的個性化配置。微信小程序是沒有全局變量window的,就算是網頁端有window其實最好也不要用,會污染全局作用域。這時候該怎么辦?給大家看看定義fundebug.test()是怎樣定義的吧:

function defineTestApi(config) {
    function testApi(name, message) {
        const event = {
            type: "test",
            apikey: config.apikey,
            name: name || "Test",
            message: message || "Hello, Fundebug!"
        };
        sendToFundebug(event);
    }
    return testApi;
}

我們使用了一個外層函數defineTestApi來共享全局配置對象config,函數中定義的testApi函數則通過return返回。

這里其實也用到了閉包,因為defineTestApi函數執行結束之后,testApi函數仍然可以使用config變量,因此config變量的生命周期超越了defineTestApi函數。關于閉包的詳細介紹,我會在這個系列的后續文章中介紹。

因此,在函數中返回函數,還是很有用的

開發者對待每一個技術點,比如閉包,應該保持謙卑,不要覺得這個也沒有用,那個也沒有用,其實只是你還沒遇到使用場景而已。關于這一點,大家可以看看我的博客《聊聊我的第一篇10萬+,同時反駁某些評論》。

函數為第一公民是函數式編程的基礎

函數為第一公民的3個特性我都介紹了,它們確實讓JavaScript更加強大,然后呢?JavaScript的騷操作大家見得多了,也不會覺得有什么神奇之處。

其實,函數是第一公民,與大家都聽過的函數式編程有著密切的關系。

First-class functions are a necessity for the?functional programming?style, in which the use of?higher-order functions?is a standard practice.?

也就是說,函數為第一公民是函數式編程的必要條件。higher-order functions,即高階函數,就是使用函數作為參數的函數,它在函數式編程中很常見。

至于什么是函數式編程,不是我一句話能講清楚的,這可以一直聊到計算機的開山鼻祖圖靈。要知后事如何,請聽下回分解。

關于JS,我打算開始寫一個系列的博客,大家還有啥不太清楚的地方?不妨留言一下,我可以研究一下,然后再與大家分享一下。也大家歡迎添加我的個人微信(KiwenLau),我是Fundebug的技術負責人,一個對JS又愛又恨的程序員。

參考

Javascript誕生記

Is JavaScript a (true) OOP language?

First-class functions in Java 8

《聊聊我的第一篇10萬+,同時反駁某些評論》

關于Fundebug

Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有陽光保險、核桃編程、荔枝FM、掌門1對1、微脈、青團社等眾多品牌企業。歡迎大家免費試用!

版權聲明

轉載時請注明作者 Fundebug以及本文地址:

https://blog.fundebug.com/201...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104983.html

相關文章

  • JavaScript深入淺出3什么垃圾回收算法?

    摘要:摘要是如何回收內存的深入淺出系列深入淺出第課箭頭函數中的究竟是什么鬼深入淺出第課函數是一等公民是什么意思呢深入淺出第課什么是垃圾回收算法最近垃圾回收這個話題非常火,大家不能隨隨便便的扔垃圾了,還得先分類,這樣方便對垃圾進行回收再利用。 摘要: JS是如何回收內存的? 《JavaScript深入淺出》系列: JavaScript深入淺出第1課:箭頭函數中的this究竟是什么鬼? Jav...

    AaronYuan 評論0 收藏0
  • JavaScript深入淺出1:箭頭函數中的this究竟什么鬼?

    摘要:箭頭函數沒有自己的值,箭頭函數中所使用的來自于函數作用域鏈。使用箭頭函數打印對于內層函數,它本身并沒有值,其使用的來自作用域鏈,來自更高層函數的作用域。 《JavaScript 深入淺出》系列: JavaScript 深入淺出第 1 課:箭頭函數中的 this 究竟是什么鬼? JavaScript 深入淺出第 2 課:函數是一等公民是什么意思呢? 普通函數與箭頭函數 普通函數指的是...

    MRZYD 評論0 收藏0
  • JavaScript深入淺出5:Chrome如何成功的?

    摘要:所做的最重要的事情,就是對成千上萬的網頁進行排序,所以它存在的意義是基于網頁的。確實有很多非常成功的產品,比如,,,但是它們其實都是收購來的。為什么呢因為要做到極簡主義,需要深刻思考用戶需求以及產品價值。 摘要: Chrome改變世界。 《JavaScript深入淺出》系列: JavaScript深入淺出第1課:箭頭函數中的this究竟是什么鬼? JavaScript深入淺出第2課:...

    luqiuwen 評論0 收藏0
  • JavaScript深入淺出4:V8引擎如何工作的?

    摘要:摘要性能彪悍的引擎。深入淺出系列深入淺出第課箭頭函數中的究竟是什么鬼深入淺出第課函數是一等公民是什么意思呢深入淺出第課什么是垃圾回收算法深入淺出第課是如何工作的最近,生態系統又多了個非常硬核的項目。 摘要: 性能彪悍的V8引擎。 《JavaScript深入淺出》系列: JavaScript深入淺出第1課:箭頭函數中的this究竟是什么鬼? JavaScript深入淺出第2課:函數是一...

    hsluoyz 評論0 收藏0
  • JS函數式編程 - 概念

    摘要:最近在看,順便看了一些函數式編程,然后半個國慶假期就沒有了。最開始接觸函數式編程的時候,第一個接觸的概念就是高階函數,和柯里化。所以我覺得最開始學習函數式編程最好先了解一些相關概念和思想會比較好。 最近在看Typescript,順便看了一些函數式編程,然后半個國慶假期就沒有了。做個筆記,分幾個部分寫吧。 最開始接觸函數式編程的時候,第一個接觸的概念就是高階函數,和柯里化。咋一看,這不就...

    Forelax 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<