function - JavaScrip的一等公民

LogicOrbit
• 阅读 826

JavaScript是一门函数式语言,function是这门语言的一等公民。所以理解function,我个人觉得是学好JavaScript这门语言最重要的一部分。

function通常作为我们的逻辑单元,通过被调用(call)来完成一个大程序里面的一部分功能。但是在JavaScript里面,一个function可以作为构造函数,通过new关键字来实例化一个对象,例如:

function DOG(){}
let dog = new DOG();
console.log(dog.constructor === DOG); // true

但是我们常常说:“function是JavaScript的第一型对象(first-class object)”。在这句话里面有个非常重要的信息就是:function是对象

是的,在JavaScript里,function是对象,而且就跟一般的对象一样有属性方法。function与一般对象唯一的区别就是,function可以被调用。那既然function是对象,那他们是否也有构造函数呢?

是的,JavaScript里面所有的function的构造函数都是Function。那既然Function是构造函数,那么是否可以通过new关键字来创建一个对象(也就是一个function)呢?答案是“yes”:

let sum = new Function('a', 'b', 'return a + b');
console.log(sum(2, 6)); // 8

用Function来创造一个function的语法是:

new Function ([arg1[, arg2[, ...argN]],] functionBody)

最后一个参数是函数体,前面是参数列表。

但是我们常常不通过Function来new一个function,通常还是利用function字面量来创建一个方法。

funtion的属性和方法

前面我们说到JavaScrip里所有的function都是对象,且他们的构造器(constructor)都是Function,那么所有的function势必会从Function上继承到一些属性和方法。下面我们就来都有哪些:

Function上可用的属性:

1: Function.prototype.length
2: Function.prototype.name
3: Function.prototype.constructor

Function上可用的方法:

1: Function.prototype.apply()
2: Function.prototype.call()
3: Function.prototype.bind()
4: Function.prototype.toString()

下面我们来对上面几个重要的属性和方法进行讲解:
1: Function.prototype.length -- 函数形参的个数

function testLength(a, b) {
    console.log(testLength.length);
}
testLength(1, 2, 3); // 2

这里一定要和arguments.length区分开。每个函数都会隐式地传入this和arguments这2个参数。arguments表示调用函数的时候,实际传入的参数,它是一个类数组对象,它也有一个length属性。arguments.length就表示实际传入的参数个数。

我们知道JavaScript是允许形参和实参个数不一致的,所以Function.prototype.length表示形参的个数arguments.length表示实参的个数。他们俩不一定相等,所以一定要把他俩区分开。

2: Function.prototype.name -- 函数的名字
每一个函数都有一个name属性,它是一个字符串,用来表示这个函数的名字。name这个属性,有些复杂,接下来我们一一来看一下:

1: 在全局作用域内定义一个函数

function funX() {};
console.log(window.funX.name);//"funX"

JavaScript有个特性就是:如果在全局作用域内定义一个function,相应地会自动在window对象上创建一个和funciton同名的属性,且把这个function赋给这个属性。

从上面的代码可以验证这一点,我们创建了funX()这个function之后,在window上有了funX这个属性,且它有一个name属性,而且name的值就是funX()的名字,也就是"funX"。

2: 在全局范围内定义一个函数表达式:

var x = function funX(){};
console.log(x.name);//"funX"

var y = function(){};
console.log(y.name);//"y"

当我们定义了一个命名函数表达式的时候,name属性就是函数的名字,而不是变量的名字;但是,当我们把一个匿名函数表达式赋值给一个变量的时候,name就是变量的名字。

以上代码是在chrome里面测试的结果,我个人觉得匿名函数表达式的时候,结果和我想的不一样,我以为这种情况name会是一个空字符串,没想到这个时候name就是变量名字。

有一点需要注意:在全局作用域下面定义函数表达式,并不会在window上创建一个同名属性。

3: Function.prototype.constructor
constructor用来表示函数的构造函数。我们说所有的函数都是Function的一个实现,那么所有函数的constructor都应该是Function。所以,如果在需要判断一个变量是否是一个函数类型的时候,我们可以这么做:

function funX() {};
if(funX.constructor === Function){ // true
    
}

通常情况下,上面的代码是没有问题的。但是constructor这属性,我们却可以随意修改:

function funX() {};
funX.constructor = {};
if(funX.constructor === Function){ // false

}

像这种情况,再通过constructor来判断是否是函数类型,就不行了。最经典和保险的做法是使用Object.prototype.toString()方法来判断是否为函数类型:

function funX() {};
funX.constructor = {};
if(Object.prototype.toString.call(funX)=== "[object Function]"){ //true
    console.log('is function');
}

toString()方法返回一个对象的描述。我们之所以要通过call()来调用Object.prototype.toString()而不是调用函数本身的toString()方法,是因为toString()也有可能会被重写,而Object.prototype.toString()是最原始的蓝本,没有人能重写它。

点赞
收藏
评论区
推荐文章
九路 九路
4年前
Go 函数是“一等公民”的理解
函数(function)作为现代编程语言的基本语法元素存在于支持各种范式(paradigm)的主流编程语言当中。无论是命令式语言C、多范式通用编程语言C,还是面向对象编程语言Java、Ruby,亦或是函数式语言Haskell、动态脚本语言Python、PHP、JavaScript,函数这一语法元素都是当仁不让的核心。Go语言以“成为新一代系统
凝雪探世界 凝雪探世界
4年前
JavaScript基础加ES6语法
JavaScript一、什么是JavaScript当下最流行的脚本语言,在世界上的所有浏览器中都有js的身影,是一门脚本语言,可以用于我们与web站点和web应用程序的交互,还可以用于后台服务器的编写,例如node.js二、语法特点基于对象和事件驱动的松散型,解释型语言单线程异步三、JavaScript作用页面的交
东方客主 东方客主
4年前
一篇文章弄明白Javascript
在一片混沌中,一个叫Function的函数开天辟地,自己创建了自己。于是,一个叫JavaScript的星球诞生了。图一:创建了自己的Function新诞生
Wesley13 Wesley13
3年前
java script三大组成部分
JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。JavaScript的三大组成部分是:1、ECMAScript:JavaScript的核心,描述了语言的基本语法(var、for、if、a
Souleigh ✨ Souleigh ✨
4年前
Swift 简介
Swift和ObjectiveC的主要区别1,编程范式Swift可以面向协议编程、函数式编程、面向对象编程。Swift语言引入了协议、协议的扩展、泛型等新特性,因此使用Swift语言可以很好地面向协议编程;Swift语言将函数和闭包提升为语言的一等公民,函数可以作为一个变量、可以作为其他函数的参数、作为其他函数的返回值等来传递,所以
Wesley13 Wesley13
3年前
JS的另类写法(书签栏工具原型)
<scripttype"text/javascript"javascript:void(function(version){varscriptTagdocument.createElement('script');scriptTag.type'text/javascript';
Stella981 Stella981
3年前
JavaScript的入门简介
什么是JavaScriptJavaScript,我们一般简称为JS,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。JavaScript现在已经被用到了很多非浏览器环境中,JavaScript基于原型编程、多范式的动态脚本语言,并支持面向对象、命令式和声明式风格。HTML、CSS、JavaScript三者不同的功能:
Wesley13 Wesley13
3年前
Java scirpt 简介
javascript简介:  JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。基本特点:  JavaScri
Stella981 Stella981
3年前
JavaScript中call()与apply()有什么区别?
今天读《JavaScript权威指南》时发现其中有段代码用到了apply方法用于递归实现数组的展开。可是我不懂这个函数的用法,因此查了一下,将资料整理如下。Javascript的每个Function对象中有一个apply方法:function.apply(thisObj,argArray)还有一个类似功能的call方法:
Stella981 Stella981
3年前
JavaScript学习总结(3)——JavaScript函数(function)
一、函数基本概念  为完成某一功能的程序指令(语句)的集合,称为函数。二、JavaScript函数的分类  1、自定义函数(我们自己编写的函数),如:functionfunName(){}  2、系统函数(JavaScript自带的函数),如alert函数。三、函数的调用方式
Stella981 Stella981
3年前
JavaScript函数式编程,“香”吗?
总说函数是JavaScript的一等公民,很多人就问了,它凭什么?其实凭的就是对于JS这种没有明确归类的“多范式语言”,函数式编程拥有着天然的优势。在JS里,函数本身就被视作对象,可以有属性,能作为参数传给函数,也能作为函数的返回结果,十分便利。而这种特性对于代码日益庞大,业务逻辑逐渐复杂的前端来说称得上是至关重要。