目录
介绍
什么是JavaScript函数?
定义函数
函数声明
函数表达式
箭头函数
函数提升
一流函数的属性
函数签名
重载
参数
默认参数
ES6之前的默认参数
默认参数ES6
函数类型
函数属性
函数方法
this对象
call()方法
apply()方法
bind()方法
总结
介绍函数对任何编程语言都是至关重要的。将小段代码隔离和/或组织成子例程的概念具有许多用途和价值。因此,它帮助我们构造了中型到大型程序,以减少重复,并使程序和/或子程序彼此模块化。
因此,本文将深入探讨JavaScript函数。此外,如果您来自C#、Java和/或C / C ++等面向对象的语言,那么阅读本文肯定会对您有所帮助。原因之一是由于我的.NET背景以及有关C#编程的类思维方式。
什么是JavaScript函数?在JavaScript语言中,函数是对象。对象?是的,它是真实的。让我们看看下面的证明:
function laugh() {
return "hahahahaha";
}
console.log(typeof(laugh)); //output: function
console.log(laugh instanceof Object); //output: true
console.log(laugh instanceof Function); //output: true
让我们看一下ECMAScript语言规范关于JavaScript函数必须说些什么。请参见下面的屏幕截图,也可以在此处访问并查看。
确认JavaScript函数是一个对象。而且,我知道您在质疑,JavaScript语言如何区分函数和对象?但是在回答之前,让我解释一下。JavaScript语言为对象定义了许多内部属性,这些内部属性由双方括号“[[]]”符号表示。
这些内部属性与JavaScript函数有什么关系?这些内部属性可以将函数与对象区分开,并且此属性为[[Call]]。此外,此[[Call]]属性对于函数而言是唯一的,表示可以执行该对象。因此,[[Call]]属性是函数专有的。这就是为什么在使用typeof运算符时返回“function”的原因。
同样,因为函数是对象。并且,它们的行为与其他编程语言相比有所不同。因此,必须对JavaScript函数有一个很好的了解。
定义函数 函数声明一个函数声明开头的function关键字,加上函数的名称。最后,函数的内容(也称为代码块)用花括号括起来。让我们在下面看一个例子。
function smile(happythought1, happythought2) {
return "My happy thoughts are " + happythought1 + " and " + happythought2;
}
函数表达式
一个函数表达式不需要function关键字后的名称。此外,这些函数被视为匿名函数,因为该函数本身没有名称。并且,它由变量或属性名称引用。
让我们看下面的例子:
const smileAgain = function (happythought1, happythought2) {
return "My happy thoughts are " + happythought1 + " and " + happythought2;
};
上面的示例代码实际上为该smileAgain变量分配了一个函数值。如您所见,函数表达式与函数声明非常相似,唯一的例外是缺少名称和分号。在提升部分,它们的差异更大。
最近,JavaScript的ES6版本引入了箭头函数。并且,其特征为“=>”(对我来说就像箭一样!)。此外,它使我们能够使用较短的语法。因此,它的行为类似于函数表达式,但是由于箭头运算符和lambda表达式的组合而看起来有所不同。
以下是有关箭头函数需要记住的内容:
- 它由零个或多个参数组成,这些参数围绕在圆括号内,也称为圆括号()。
- =>操作符紧随其后
- 在箭头运算符之后,其后是一个函数主体。请记住,如果存在多个表达式,则仅需用大括号{}括住主体。因此,如果只有一个表达式,则可以省略花括号。
请参见下面的代码段:
//declarative function
var showFavoriteLanguage(language) {
return `I love ${language}`;
}
//arrow function equivalent
const showFavoriteLanguage= (language) => `I love ${language}`;
在本节中,让我们将函数声明转换为箭头函数。首先,让我们定义一个函数。
function getProductOfTwoNumbers(num1, num2) {
return num1 * num2;
}
其次,将其转换为箭头函数。
const getProductOfTwoNumbers = (num1, num2) => {
return num1 * num2;
}
看起来像一个函数表达式。对?想要一些样式吗?我们可以删除花括号。
const getProuductOfTwoNumbers = (num1, num2) => num1 * num2;
很好!对我来说看上去很好。
如果您很好奇,如果我们只有一个参数该怎么办?让我们在下面看一个例子。
//gets the first element in the passed array
const getFirstElement = (arr) => arr[0];
//squares the passed number
const squareNum = (num) => Math.pow(num, 2);
函数提升
在上一节中,我们了解了如何定义function。此外,我们已经看到函数声明和函数表达式有多么相似,但是在某些方面有所不同。
函数声明被提升到顶部。因此,您可以在代码中使用函数后定义函数,而不会引起错误。
让我们看下面的例子:
console.log(chuckle()); //output: Hehehehe
function chuckle() {
return "Hehehehe";
}
请记住,函数提升仅发生在函数声明中。原因之一是预先确定了函数名称。而函数表达式(包括箭头函数)不能提升,因为它仅通过变量来引用。
这就是使JavaScript函数强大的原因。因为JavaScript语言具有一流的函数。而且,根据MDN(Mozilla开发人员网络):
“当一种编程语言的函数像任何其他变量一样被对待时,它被称为具有一流的函数。例如,用这种语言,一个函数可以作为参数传递给其他函数,可以由另一个函数返回,也可以作为值分配给变量。”
并且,您可以在这里查找。
这里有些例子:
- 将函数分配给变量:
//assign a variable to a function
const love = function () {
return "I love JavaScript";
}
//output: I love JavaScript
console.log(love());
//end of assign a variable to a function
- 向对象添加函数:
//add function to objects
const sayHello = function (name) {
return "Hi! My name is " + name;
}
const customer = {
name: "Jin Vincent N. Necesario",
sayHello: sayHello
};
let name = customer.name;
//output: Hi! My name is Jin Vincent N. Necesario
console.log(customer.sayHello(name));
//end of function to objects
- 将函数作为参数传递给其他函数:
//pass function as an argument
function sayFavorite() {
return "Hi! My Favorite programming language is ";
}
function favoriteLanguage(func1, language) {
return func1() + language;
}
//output: Hi! My Favorite programminglanguage is JavaScript
console.log(favoriteLanguage(sayFavorite, "JavaScript"));
//end of pass function as an argument
- 从另一个函数返回函数:
//return a function
function followYou() {
return function () {
return "Your part of me I can't let go!!!";
};
}
const follow = followYou();
//output: Your part of me I can't let go!!!
console.log(follow());
//end of return a function
函数签名
如果您来自诸如C#,Java和/或C / C ++的静态语言,则这些语言支持函数重载。并且,单函数具有多个签名的能力。此外,函数签名由函数名称,参数数量和该函数接受的参数类型组成。但是,JavaScript语言函数没有签名。因此,JavaScript缺少函数重载。
让我们尝试看看当我们声明两个具有相同名称的函数时会发生什么。
function giveLove(act){
console.log(act);
}
function giveLove() {
console.log("Trust your partner");
}
//output: Trust your partner
giveLove("Love and trust your partner");
根据我们的示例,如果您使用的是面向对象的语言,则可以期望输出为"Love and trust your partner"。而且,由于JavaScript缺少重载,因此它执行了没有参数的函数。因此,输出为"Trust your partner"。
要理解的另一个概念是JavaScript函数可以传递任何数量的参数而不会引起错误。这是因为函数参数存储为称为arguments的“类似数组的对象”。
如果您想了解有关数组对象的更多信息,请访问此处。
而且,参数可以增长为包含许多值。length属性确定该函数中存在多少个值。最后,arguments对象可在任何函数中自动使用。因此,函数中存在的命名参数本质上是为了方便起见,并且不限制函数可以接受的参数数量。
让我们看下面的例子:
function decidedToLove() {
let len = arguments.length,
messageResult = "",
counter = 0;
while (counter < len) {
messageResult += counter === 0 ? arguments[counter]: `,${arguments[counter]}`;
counter++;
}
return messageResult;
}
//output: I'm in love
console.log(decidedToLove("I'm in love"));
//output: Don't be mean,Leave my heart alone
console.log(decidedToLove("Don't be mean", "Leave my heart alone"));
//output: love,trust,appreciate
console.log(decidedToLove("love", "trust", "appreciate"));
默认参数
在ES6之前,没有明确的方法为函数参数分配默认值。因此,开发人员可以在为参数分配默认值之前检查这些参数。
让我们看下面的例子:
function yourAmazing(arg1, arg2, arg3) {
arg1 = arg1 || "arg1";
arg2 = arg2 || "arg2";
arg3 = arg3 || "arg3";
return `${arg1}, ${arg2}, ${arg3}`;
}
//using all the default values
//output: arg1, arg2, arg3
console.log(yourAmazing());
//using the last two default values
//output: my-first-argument, arg2, arg3
console.log(yourAmazing("my-first-argument"));
//using the last default value
//output: my-first-argument, my-second-argument, arg3
console.log(yourAmazing("my-first-argument", "my-second-argument"));
//sending all with values
//output: my-first-argument, my-second-argument, my-third-argument
console.log(yourAmazing("my-first-argument", "my-second-argument", "my-third-argument"));
让我们看另一个示例,这次检查传递的参数是否未定义。
function areYouAnAngel(arg1, arg2, arg3) {
arg1 = arg1 === undefined ? 1 : arg1;
arg2 = arg2 === undefined ? 2 : arg2;
arg3 = arg3 === undefined ? 3 : arg3;
return `${arg1}, ${arg2}, ${arg3}`;
}
//using all the default values
//output: 1, 2, 3
console.log(areYouAnAngel());
//using the last two default values
//output: my-first-argument, 2, 3
console.log(areYouAnAngel("my-first-argument"));
//using the last default value
//output: my-first-argument, my-second-argument, 3
console.log(areYouAnAngel("my-first-argument", "my-second-argument"));
//sending all with values
//output: my-first-argument, my-second-argument, my-third-argument
console.log(areYouAnAngel("my-first-argument", "my-second-argument", "my-third-argument"));
默认参数ES6
最近,JavaScript语言具有一种新的语法,该语法可以更轻松,更优雅地执行默认参数。万岁!
- 默认参数示例:
function myGifts(gift1 = "health", gift2 = "wealth", gift3 = "love") {
return `${gift1}, ${gift2}, ${gift3}`;
}
//using all the default values
//output: health, wealth, love
console.log(myGifts());
//using the last two default values
//output: healthy body, wealth, love
console.log(myGifts("healthy body"));
//using the last default value
//output: healthy body, cash-flow, love
console.log(myGifts("healthy body", "cash-flow"));
//sending all with values
//output: healthy body, cash-flow, family
console.log(myGifts("healthy body", "cash-flow", "family"));
- 将未定义的值传递给默认参数:
function youAreGreat(talent1 = 'write', talent2 = 'speak', talent3 = 'code') {
return `${talent1}, ${talent2}, ${talent3}`;
}
//using all the default values
//output: write, speak, code
console.log(youAreGreat());
//output: read and write, speak, code
console.log(youAreGreat("read and write", undefined, undefined));
//output: write, teach and speak, code
console.log(youAreGreat(undefined, "teach and speak", undefined));
//output: write, speak, write books
console.log(youAreGreat(undefined, undefined, "write books"));
- 在默认参数内使用表达式:
function myCashGifts(gift1 = 1000, gift2 = 2000,
gift3 = (Math.random() * (5000 - 1000) + 1000)) {
return `Your total cash: $${gift1 + gift2 + gift3}`;
}
//note: the value is random the output should be different
//output: Your total cash: $4307.070424503042
console.log(myCashGifts());
函数类型
同样,JavaScript函数是对象。因此,函数具有与其他对象一样的属性和方法。让我们看看如何使用这些属性和方法。
函数属性- length属性确定函数中的总参数。
- prototype属性引用实际的函数对象。
让我们看一个函数属性的例子:
function setGift(gift1, gift2) {
return `My gifts this coming Christmas are ${gift1} and ${gift2}`;
}
//output: 2
console.log(setGift.length);
//output: object {}
console.log(setGift.prototype);
函数方法
JavaScript中的所有作用域都有一个this对象,代表该函数的调用对象。例如,在全局范围内,this表示全局对象(window)。此外,一旦函数在附加到对象时被调用,默认情况下的this值等于该对象。因此,您可以引用this而不是直接引用方法内部的对象。
让我们看下面的例子:
function showFullName() {
console.log(this);
console.log(this.name);
}
const name = "Jin Vincent Necesario";
const person = {
name: "Jin Necesario",
showFullName: showFullName
}
const pet = {
name: "Bruno",
showFullName: showFullName
}
//this value is equivalent to window object
//output: Jin Vincent Necesario
showFullName();
//this value is equivalent to person object
//output: Jin Necesario
person.showFullName();
//this value is equivalent to pet object
//output: Bruno
pet.showFullName();
了解this函数的价值是使用JavaScript进行良好的面向对象编程的关键。有三种方法,使您能够改变this的值,这些就是call,apply和bind方法。
当您要操纵this的值时,apply()和call()方法几乎相同。唯一的区别是,apply()需要类似数组的对象,而call()需要传递充当this和所需参数的对象。让我们通过示例逐一查看它们。
call()方法function showFullName(caller) {
return `Caller: ${caller} having a value of ${this.name}`;
}
window.name = "Jin Vincent Necesario";
const person = {
name: "Jin Necesario"
}
const pet = {
name: "Bruno"
}
//output: Caller: global, the window object having a value of Jin Vincent Necesario
console.log(showFullName.call(this.window, "global, the window object"));
//output: Caller: person variable having a value of Jin Necesario
console.log(showFullName.call(person, "person variable"));
//output: Caller: pet variable having a value of Bruno
console.log(showFullName.call(pet, "pet variable"));
apply()方法
function showFullName(caller, param1) {
return `${param1}. The caller: ${caller} having a value of ${this.name}.`;
}
window.name = "Jin Vincent Necesario";
const person = {
name: "Jin Necesario"
}
const pet = {
name: "Bruno"
}
//output: Hi!. The caller: global, the window object having a value of Jin Vincent Necesario.
console.log(showFullName.apply(this.window, ["global, the window object", "Hi!"]));
//output: Hello!. The caller: person variable having a value of Jin Necesario.
console.log(showFullName.apply(person, ["person variable", "Hello!"]));
//output: Good day!. The caller: pet variable having a value of Bruno.
console.log(showFullName.apply(pet, ["pet variable", "Good day!"]));
bind()方法
如果您想要一个新的函数实例,其this值绑定到您提供的对象。让我们看下面的例子:
const bike = {
speed: 10,
start: function () {
return `${this.speed} Km/h`;
}
};
const motorcycle = {
speed: 40,
start: function () {
return `${this.speed} Km/h`;
}
}
let upgradeBike = bike.start.bind(motorcycle);
//output: 40 Km/h
console.log(upgradeBike());
总结
在本文中,我们讨论了有关JavaScript函数的许多概念。我们首先回答:什么是JavaScript函数,如何定义函数,为什么JavaScript是一流函数。最后,我们研究了函数签名和函数类型。