javascript声明函数-JavaScript 第 2 课:函数成为一等公民意味着什么?

2023-09-05 0 7,189 百度已收录

摘要:什么是听起来很酷的一等公民?

《用简单而深入的语言解释JavaScript》系列:

我看到上面提到的一篇关于JavaScript历史的文章:JavaScript借用了Scheme语言,将函数提升到了“一等公民”的地位。

一等公民这个名字听起来很宏伟,但也相当冗长。 这与翻译无关,因为包括我在内的很多一等公民都不知道该说什么。

JavaScript 函数是一等公民是什么意思? 让我向您解释一下并给您一些想法。

一等公民的定义

据维基百科介绍,编程语言中的一等公民概念早在 20 世纪 60 年代就由荷兰计算机科学家 Christopher Strachey 提出。 那时,没有个人电脑,没有互联网,没有浏览器,也没有 JavaScript。

可能很多人和我一样,没有听说过克里斯托弗·斯特雷奇(Christopher Strachey)javascript声明函数,他只是提出了一等公民的概念,没有给出严格的定义。

关于一等公民,我从《编程语言语用学》一书中找到了一个权威的定义javascript声明函数,它是很多院校编程语言设计的教材。

一般来说,如果编程语言中的值可以作为参数传递、从子例程返回或分配给变量,则该值被称为具有第一类状态。

也就是说,在编程语言中,一等公民可以用作函数参数,也可以用作函数返回值,也可以用作变量的形式参数。

例如,字符串在几乎所有编程语言中都是一等公民。 字符串可以用作函数参数,字符串可以用作函数返回值,字符串还可以用作变量的形式参数。

对于各种编程语言来说,函数不一定是一等公民,比如Java 8之前的版本。

对于JavaScript来说,函数可以给变量赋予形式参数,也可以作为函数参数,还可以作为函数返回值,所以JavaScript中的函数是一等公民。

函数作为函数参数

回调函数(callback)是JavaScript异步编程的基础。 它实际上使用函数作为函数参数。 比如常用的setTimeout函数的第一个参数就是函数:

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

JavaScript函数作为函数参数,或者回调函数,作为异步的一种形式,大家都写了很多。 其实它还有其他的应用场景。

在对一些复杂的数据结构进行排序时,可以使用自定义的比较函数作为参数:

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

javascript声明函数-JavaScript 第 2 课:函数成为一等公民意味着什么?

可以看出hello变量的类型是“function”。

在其他一些First-class函数的定义中,还要求该函数可以存储在其他数据结构中,例如链表和对象,JavaScript也支持这些数据结构。

在计算机科学中,如果一种编程语言将函数视为一等公民,则该语言被称为具有一流函数。 这意味着该语言支持将函数作为参数传递给其他函数,将它们作为其他函数的值返回,并将它们分配给变量或将它们存储在数据结构中。

函数可以保存到Object,这意味着函数成为一个Object。 我在《JavaScript第一课:箭头函数中的this到底是什么?》中写到 》中提到,当函数作为对象调用时,它的 this 值就是该对象。 这与Java等面向对象语言是一致的。 因此,在JavaScript存在之前,它在一定程度上支持面向对象编程,但当然是比较弱的。

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!”。

javascript声明函数-JavaScript 第 2 课:函数成为一等公民意味着什么?

我估计有人会在这里打断我,因为没有必要写这样的示例代码,因为有一个更简单的方法:

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

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

但这只是一个简单的例子。 在一些复杂的实际场景中,函数返回函数还是很有用的。 这是一个简单的例子。

我们Fundebug在使用陌陌小程序BUG监控插件时,将不同API的定义拆分到不同的文件中,但这种API需要共享一些全局属性,比如用户的个性化配置。 微信小程序没有全局变量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,通过return返回函数中定义的testApi函数。

这里虽然也使用了闭包,但是在defineTestApi函数执行完成后,testApi函数仍然可以使用config变量,所以config变量的生命周期已经超过了defineTestApi函数。 我将在本系列后续文章中详细介绍闭包。

因此,函数内返回函数还是很有用的。

开发者在处理每一个技术点,比如闭包时,都应该保持谦虚的态度,不要认为这个没用,那个没用。 其实只是你还没有遇到使用场景而已。 关于这一点,大家可以看看我的博客《一边批评个别评论一边谈我的第一篇10万+文章》。

javascript声明函数-JavaScript 第 2 课:函数成为一等公民意味着什么?

函数作为第一公民是函数式编程的基础

我已经介绍了使职能成为第一公民的三个特征。 它们确实让 JavaScript 变得更加强大。 接下来是什么? 你已经见过很多 JavaScript 的炫酷操作,你不会认为它们有什么神奇之处。

事实上,函数是第一公民,与大家都听说过的函数式编程密切相关。

一等函数是函数式编程风格的必需品,其中使用高阶函数是标准做法。

换句话说,函数作为第一公民是函数式编程的必要条件。 高阶函数是使用函数作为参数的函数。 它们在函数式编程中非常常见。

至于什么是函数式编程,我无法用一句话解释清楚。 我们总能谈论计算机鼻祖图灵。 想知道接下来会发生什么,请听下一章。

关于JS,我准备开始写一系列的博客。 您还有什么不清楚的地方吗? 为什么不发表评论,以便我可以研究并与您分享。 也欢迎您添加我个人的Momo(KiwenLau)。 我是Fundebug的技术总监,一个对JS又爱又恨的程序员。

关于 Fundebug 的参考

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java在线应用的实时BUG监控。 自2016年双十一即将上线以来,Fundebug已累计处理超过10亿次错误事件。 付费客户包括阳光保险、核桃编程、荔枝FM、掌门1对1、微脉、青团等多家品牌公司。 欢迎您免费试用!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 javascript javascript声明函数-JavaScript 第 2 课:函数成为一等公民意味着什么? https://www.wkzy.net/game/195604.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务