共计 6029 个字符,预计需要花费 16 分钟才能阅读完成。
本文首发自「慕课网」,想理解更多 IT 干货内容,程序员圈内热闻,欢送关注!
作者 | 慕课网精英讲师 然冬
在 JavaScript 中,函数是头等 (first-class) 对象,因为它们能够像任何其余对象一样具备属性和办法。它们与其余对象的区别在于函数能够被调用。简而言之,它们是 Function 对象。(MDN)
函数就是一段代码片段,调用函数就是执行函数中的代码。
- 函数的应用
1.1 语法
函数应用前通常与变量一样须要先进行申明,用 function 关键字定义函数。
// 常见的函数的定义形式
function 函数名(参数 1, 参数 2, …) {
代码片段;
return 返回值;
}
// 调用函数 (执行函数中的代码)
var 函数的返回值 = 函数名 (参数 1, 参数 2, …);
代码块 123456789
调用函数就是执行函数中的代码
参数是调用函数的时候传递过来的,在函数执行过程中能够拜访到
函数执行结束后能够有一个返回值,调用函数的中央能够接管到这个返回值
1.2 调用函数
应用 函数名() 的形式即可调用一个函数
以下是一个最简略的函数:
function say() {
console.log(‘hello’);
}
say(); // 输入:”hello”
代码块 12345
调用这个函数就会在控制台输入 hello 字符串。
这个函数没有返回值,默认会返回一个 undefined。
1.3 带有参数与返回值的函数
在申明函数的时候,能够对参数也做上阐明
假如有一个需要,须要一个计算三角形周长的函数。
计算三角形周长则须要晓得三角形三条边各自的长度,而后将他们求和。
定义函数的时候就能够将三条边作为参数进行申明。
function calcPerimeter(a, b, c) {
// a, b, c 别离代表三条边
var sum = a + b + c;
return sum;
}
// 调用函数 并将返回值赋值给 perimeter
var perimeter = calcPerimeter(3, 4, 5);
代码块 123456789
在调用函数的时能够传递值过来,这些值能够在函数中被拜访。
在以上 calcPerimeter 函数被调用的时,传递了 3, 4, 5 三个值。
三个值对应到函数申明时定义的三个参数 a, b, c。
所以函数执行过程中 sum 的值为 3 + 4 + 5,即 12,随后 sum 被作为返回值进行返回。
最终变量 perimeter 也会被赋值为 12。
- 怎么使用函数
2.1 正当包装内容
函数能够对代码进行封装,让逻辑更加清晰。
比方如下代码块:
// 改写前
var num = 10;
var flag = false;
var i;
var len;
for (i = 2, len = num – 1; i <= len; i++) {
if (num % i === 0) {
flag = true;
break;
}
}
console.log(flag);
代码块 123456789101112131415
以上代码第一眼可能无奈看出具体在做什么,仅须要做一点批改,就能有所改善。
// 改写后
function isPrimeNumber(num) {
var flag = false;
var i;
var len;
for (i = 2, len = num – 1; i <= len; i++) {
if (num % i === 0) {
flag = true;
break;
}
}
return flag;
}
var num = 10;
var result = isPrimeNumber(num);
console.log(result);
代码块 12345678910111213141516171819202122
改写后的代码仿佛多了几行,然而将其中外围局部包装成了函数。
通过 isPrimeNumber 函数名能够很容易的理解到这一段代码作用是用来判断一个数是否为质数。
当然有个前提就是起一个 能够让大部分人看得懂 的函数名。
2.2 优良的函数名
优良的函数名能够帮忙别人更容易了解代码,同时当本人一段时间后再回头看代码时,能更容易进入过后写代码时候的思维模式等。
这里提供几个函数命名的倡议,具体的命名能够依据团队标准、个人成长等做调整。
2.2.1 拼写精确
精确的拼写非常重要,绝大多数状况下函数名都会是英文单词组成的。
当然许多时候手一快可能就少了一个字母,或者错将 wrap 进行乾坤大挪移拼写成了 warp。
许多状况是无奈防止的,常常须要自检。
当然能够借助一些单词的查看插件,如 Visual Studio Code 能够借助 Code Spell Checker 插件来查看单词的正确性。
再者碰到想起的函数名然而单词拼写不进去,尽可能翻词典,与日俱增能有大量的词汇积淀。
2.2.2 尽量不应用拼音或者混用拼写
尽量不要应用拼音或者是首字母缩写。
以下函数名或者会造成困扰:
function jslsh() {}
function jsNumber() {}
代码块 123
以上是计算两数和函数的命名,可能只有天和地晓得这个是什么意思。
当然,如果是本人写 demo 或者测试代码的时候,其实不须要思考这么多。
2.2.3 有“状态”的函数名
如碰到函数性能是判断是否、有没有、能够的时候,能够带上一些前缀,比方:
// 是否登入
function isLogin() {}
代码块 12
同时能够正当的应用动词,比方关上文件就能够应用 openFile 函数名,具体的状态能够依据语境、函数作用、集体习惯等做调整应用。
2.2.4 正当应用缩写
应用词语的缩写尽量应用通用的缩写
如:
pwd – password
mgr – manager
del – delete
…
这些缩写大部分开发者是能够看的懂的缩写。
- 函数示例
3.1 计算圆的面积
剖析:依据圆面积公式 S=π·r·r,其中 S 就是要求的值,即函数的返回值,π 是常量(固定的一个值),半径 r 是未知数,所以 r 就能够设计成参数
function circleArea(r) {
var pi = 3.1415926;
return pi * r * r;
}
// 计算半径为 10 的圆的面积
var area = circleArea(10);
代码块 12345678
3.2 判断某个 DOM 元素是否含有某个类名
剖析:
某个 DOM 和某个类名能够阐明有两个未知量,能够设计成两个参数。
依据形容也能够确定一个 某个 DOM 的类型是个 DOM 对象,某个类名是个字符串
只有拿到这个 DOM 的 class 属性,判断外面是不是含有这个类型即可失去后果
function hasClass(el, className) {
// el 是 element 的缩写,示意一个 dom 元素
// 如果没有元素 则返回
if (!el) {
return false;
}
// 依据空格宰割成数组
// 能够不应用 split 办法,应用字符串也能够用 indexOf 匹配
var classList = el.className.split(‘ ‘);
// 判断是否存在
if (classList.indexOf(className) >= 0) {
return true;
}
return false;
}
代码块 12345678910111213141516171819
- 函数的其余常识
以下扩大内容可能须要肯定的常识积攒,遇到不懂的中央能够停下脚步,先学习下一章节
4.1 函数表达式
以上篇幅的函数其实都通过函数申明的形式来定义,还有一种形式就是应用函数表达式定义函数。
// 函数申明
function add(a, b) {
return a + b;
}
// 函数表达式
var add = function(a, b) {
return a + b;
};
代码块 123456789
通过上述例子能够看出写法上的区别就是函数表达式是将函数赋值给了变量。
这两种形式创立的函数最大的区别在于,不能提前调用应用函数表达式创立的函数
光看句子有点形象,举个例子?:
var num1 = add1(1, 2);
var num2 = add2(3, 4);
// 函数申明
function add1(a, b) {
return a + b;
}
// 函数表达式
var add2 = function(a, b) {
return a + b;
};
代码块 12345678910111213
下面一段代码在执行的时候会报 add2 is not a function 的谬误,示意 add2 不是函数,也就是说 add2 不能被提前应用,而 add1 能够。
具体起因能够查看执行上下文章节。
4.2 函数作用域
函数有他本人的作用域,函数内申明的变量等通常状况下不能被内部拜访,然而函数能够拜访到内部的变量或者其余函数等
var a = 1;
function fn() {
var b = 2;
console.log(a); // 输入:1
console.log(b); // 输入:2
}
fn();
console.log(b); // ReferenceError: b is not defined
代码块 123456789101112
执行以上代码会报 b is not defined 谬误。
4.3 匿名函数
没有名字的函数就是一个匿名函数
var fn = function() {
console.log('我是一个匿名函数');
};
代码块 123
除了在函数表达式中会呈现匿名函数,还有许多场景。
绝对常见的一个就是自执行匿名函数,MDN 官网翻译为立刻调用函数表达式。
自执行就是这个函数申明后就会立刻执行,自执行的匿名函数通常会被用来造成独立的作用域。
如:
(function() {
var num = 1;
alert(num);
})();
代码块 12345
这是一个自执行的匿名函数,这个匿名函数是被包裹了一段括号后才被调用的。
以下这段代码会报错:
// 报错
function() {
var num = 1;
alert(num);
}();
代码块 123456
浏览器会通知你必须给函数一个名字。
通过括号包裹一段函数,让 js 引擎辨认成他是一个函数表达式,再对他进行执行,就不会报错,这是加括号的起因。
同理,能够应用 +,! 等运算符代替括号,让一个匿名函数成为一个函数表达式即可。
大部分第三方框架都会通过一个自执行的匿名函数包裹代码,与浏览器全局环境隔离,防止净化到全局环境。
4.4 具备函数名的函数表达式
函数表达式进行申明的时候也能够应用具名函数
var count = function fn(num) {
console.log('我是一个函数');
};
代码块 123
以上这段代码是不会报错的,然而不能通过 fn 拜访到函数,这里的 fn 只能在函数外部进行拜访,通常在应用递归的模式做计算的时候会用到这种写法。
var count = function fn(num) {
if (num < 0) {return num;}
return fn(num - 1) + num;
}
count(5);
代码块 123456789
下面这个例子,就是在函数外部拜访 fn 调用本人,应用递归的模式求和。
注:递归相干的常识能够参考相干文献进行学习
4.5 arguments
arguments 是一个对应于传递给函数的参数的类数组对象。(MDN)
通常状况下函数都具备 arguments 对象,能够在函数外部间接拜访到。
他是一个类数组,即长得很像数组,成员都是用数字编号,同时具备 length 属性。
arguments 中寄存着以后函数被调用时,传递过去的所有参数,即使不申明参数,也能够通过 arguments 取到传递过去的参数。
function sum() {
console.log(arguments);
}
sum(1, 2, 3, 4);
代码块 12345
执行上述代码,能够看到在控制台输入了一个对象,寄存的就是所有传递过来的参数,利用这一个性,就能够不限度参数个数,或者让函数做中转站(拦挡函数),利用 arguments 将参数传递给另一个函数。
如,一个不确定用户输出的参数个数的求和函数:
function sum() {
var total = 0;
var i;
var len;
for (i = 0, len = arguments.length; i < len; i++) {
total += arguments[i];
}
return total;
}
var total = sum(1, 2, 3, 4, 15);
console.log(total); // 输入:25
代码块 1234567891011121314
通过循环遍历 arguments 对象,就能够失去所有参数,而后做累加就能够达到求和的目标。
4.6 函数和办法
办法在实质上是个函数。
通常都能听到“调用一下某个办法”,“取到某个办法的返回值”,这里的办法其实就是一个函数。
个别办法是用来形容对象的某个行为的,然而平时咱们会混用,口头交换的时候会常常把函数间接称作办法。
只有本人了解,不须要去纠结函数和办法到底是什么,也不必特意纠正他人的说法,大家都能听得懂就行。
4.7 JS DOC 正文
应用 JS DOC 形容函数是十分良好的习惯,良好的 JS DOC 书写还能够应用工具疾速生成文档。
JS DOC 对函数的形容大体如下:
/**
- 这是这个求幂函数 计算 x 的 y 次方
- @param {Number} x – 底数
- @param {String} y – 指数
*/
function pow(x, y) {
// ...
}
代码块 12345678
除此之外还能够形容返回值等。
4.8 纯函数与副作用
所谓纯函数,就是没有副作用的函数
一个函数从执行开始到完结,没有对外部环境做任何操作,即对外部环境没有任何影响(没有副作用),这样的函数就是纯函数。
纯函数只负责输入输出,对于一种输出只有一种函数返回值。
如果函数中存在 Math.random 这种影响返回值的函数,也不能算是纯函数。
// 纯函数
function add(a, b) {
return a + b;
}
// 非纯函数
var person = {name: ‘ 小明 ’};
function changeName {
person.name = ‘ 小红 ’; // 影响了函数外的内容,产生了副作用
}
代码块 12345678910
4.9 构造函数
当一个函数与 new 关键字一起被调用的时候,就会作为一个构造函数。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log('我是' + this.name);
};
var person = new Person(‘ 阿梅 ’, 12);
person.say();
console.log(person);
代码块 1234567891011121314
能够看到当函数作为结构函数调用的时候,默认返回的是一个对象。
仔细的读者仔细观察就能发现,构造函数的默认返回值是函数体内的 this。
事实上构造函数的执行有肯定流程:
创立一个空对象,将函数的 this 指向这个空对象
执行函数
如果函数没有指定返回值,则间接返回 this(一开始创立的空对象),否则返回指定返回值
了解这个流程,就能了解构造函数的返回值。
具体的函数的 prototype 属性等能够参阅原型章节。
- 小结
函数个性绝对较多,也是 JavaScript 的外围之一。
函数能够用于封装代码,提供代码的复用率和可读性,在大部分状况下,当两段代码具备超高类似度时,该当设计成函数,不同的局部应用参数进行辨别。
欢送关注「慕课网」,发现更多 IT 圈优质内容,分享干货常识,帮忙你成为更好的程序员!