深入了解JavaScript函数(译文)
By S.F.
本文链接 https://www.kyfws.com/news/deep-dive-into-javascript-functions/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 9 分钟阅读 - 4491 个词 阅读量 0深入了解JavaScript函数(译文)
原文地址:https://www.codeproject.com/Articles/5280603/Deep-Dive-Into-JavaScript-Functions
译文由本站翻译
前言
本文是对JavaScript函数的深入解释.将涵盖主题,例如函数声明,一等函数,提升,签名和函数类型.
介绍
函数对任何编程语言都是至关重要的.将小段代码隔离和/或组织成子例程的概念具有许多用途和价值.因此,它帮助我们构造了中型到大型程序,以减少重复,并使程序和/或子程序彼此模块化. 因此,本文将深入探讨JavaScript函数.此外,如果您来自诸如C#,Java和/或C/C ++之类的面向对象的语言,那么阅读本文绝对会对您有所帮助.原因之一是由于我的.NET背景以及有关C#编程的类思维方式.
目录
- 什么是JavaScript函数?
- 定义功能
- 功能声明
- 函数表达式
- 箭头功能
- 功能吊装
- 为什么JavaScript被称为一流函数?
- 功能签名
- 超载
- 参数
- 默认参数
- 功能类型
- 功能属性
- 功能方法
- call()方法
- apply()方法
- bind()方法
- 概要
什么是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函数必须说的内容.请参见下面的屏幕截图,也可以在[此处]访问并查看它(https://www.ecma-international.org/ecma-262/10.0/index.html#sec-terms-and-definitions-function).
确认JavaScript函数是一个对象.而且,我知道您在质疑,JavaScript语言如何区分功能和对象?但是在回答之前,让我解释一下. JavaScript语言为对象定义了许多内部属性,这些内部属性由方括号" [[]]“表示.
这些内部属性与JavaScript函数有什么关系?这些内部属性可以将函数与对象区分开,并且该属性是[[Call]].此外,此[[Call]]属性是函数所独有的,表示可以执行该对象.因此,[[Call]]
属性是功能专有的.这就是为什么在使用typeof
运算符时,它返回” function"的原因.
同样,因为函数是对象.而且,它们的行为与其他编程语言相比有所不同.因此,必须对JavaScript函数有一个很好的了解.
定义功能
功能声明
功能声明以功能关键字开头,加上功能名称.最后,函数的内容(也称为代码块)用花括号括起来.让我们在下面看一个例子.
function smile(happythought1, happythought2) {
return "My happy thoughts are " + happythought1 + " and " + happythought2;
}
函数表达式
“功能"表达式不需要在"功能"关键字之后输入名称.此外,这些"功能"被认为是匿名"功能”,因为"功能"本身没有名称.并且,它由变量或属性名称引用. 让我们在下面看一个例子.
const smileAgain = function (happythought1, happythought2) {
return "My happy thoughts are " + happythought1 + " and " + happythought2;
};
上面的示例代码实际上将函数值分配给变量smileAgain
.如您所见,函数表达式与函数声明非常相似,唯一的例外是缺少名称和分号.它们在起重部分的差异更大.
箭头功能
最近,JavaScript的ES6版本引入了arrow函数.并且,其特征为"=>
"(对我来说就像箭一样!).此外,它使我们能够使用较短的语法.因此,它的行为类似于函数表达式,但是由于箭头运算符和lambda表达式的组合而看起来有所不同.
以下是有关箭头功能需要记住的事项:
- {} 请参见下面的代码段.
//declarative function
function 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
声明和function
表达式有多么相似,但是在某些方面有所不同.
函数声明被提升到顶部.因此,您可以在代码中使用函数后定义函数,而不会引起错误.
让我们在下面看一个例子.
console.log(chuckle()); //output: Hehehehe
function chuckle() {
return "Hehehehe";
}
请记住,函数提升仅发生在函数声明中.原因之一是预先确定了功能名称.同时,函数表达式(包括箭头函数)无法吊起,因为它仅通过变量来引用.
为什么JavaScript被称为一流函数?
这就是使JavaScript函数强大的原因.因为JavaScript语言是一流的功能.而且,根据MDN(Mozilla开发人员网络): 并且,您可以在此处进行查找. 以下是JavaScript是一流功能的一些原因:
//assign a variable to a function
const love = function () {
return "I love JavaScript";
}
//output: I love JavaScript
console.log(love());
//end of assign a varaible 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");
根据我们的示例,如果您使用的是面向对象的语言,那么您期望的输出应该是"“爱与信任您的伴侣”".而且,由于JavaScript缺少重载,因此它执行了没有参数的函数.因此,输出为"“信任您的伴侣”".
参量
要理解的另一个概念是JavaScript函数可以传递任何数量的参数而不会引起错误.这是因为函数参数存储为称为自变量的"类数组对象". 如果您想了解更多有关类数组对象的信息,可以访问[here](https://jinnecesario.com/2020/09/13/es6-new-array-methods/#what-is-an-array-like -目的). 而且,参数可以增长为包含许多值. 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之前的默认参数
在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函数是对象.因此,函数具有与其他对象一样的属性和方法.让我们看看如何使用这些属性和方法.
功能属性
- 长度
- 原型 让我们看一个关于函数属性的例子.
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是一流函数.最后,我们研究了函数签名和函数类型. 希望您喜欢我喜欢写这篇文章.敬请期待更多.直到下次,编程愉快!请不要忘记关注/订阅,添加书签,赞和/或评论.干杯!谢谢你!
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
Javascript topics ECMAScript6 ES6 properties arguments class 新闻 翻译