这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
函数的意义
在数学中,函数被定义为f(x) = x + 2 类似这样的形式,在后续引用到f(x)我们就知道他指的是x + 2这样的过程。在编程语言中同样也是如此。
当我们重复使用某种过程时,我们就可以把它抽象为一个方法。
function addTow(x){
return x + 2;
}
当我们再一次需要使用这样的过程时,我们就可以调用方法来代替重复书写过程。
当这样子的过程变得复杂,比如面积公式,他带来的方便程序,相信可以很容易感受到。
定义函数
第一种直接定义
function abs(x) { // function 为函数声明 abs为函数名称 (x)为函数参数,可以为多个,用逗号隔开 不同于Java不需要定义类型 {}括号为函数体
if (x >= 0) {
return x;
} else {
return -x;
}
}
函数体内部的语句在执行时,一旦执行到
return时,函数就执行完毕,并将结果返回如果没有
return语句,函数执行完毕后也会返回结果,只是结果为undefined。
第二种 匿名函数
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}; //此处的分号 代表赋值语句 = 的结束。
像这种没有给函数名称命名的函数,为匿名函数。虽然他没有取名,但是他赋值给了变量abs,所以通过变量abs也可以调用该函数。
以上两张方式完全等价。
调用函数
调用函数时,我们只需要写入函数名,并且按照顺序传入参数即可。
abs(1);
//允许传入任意个参数不影响试用,函数会直接抛弃这些多余参数
abs(1,"a");
abs();//返回 NaN 没有传入数据,函数体内x为undefined,计算结果为NaN(Not a Number)
函数内部还会自动有一个arguments关键字,它指向当前函数被传入的所有参数。
function foo(x) {
console.log('x = ' + x); // 10
for (var i=0; i<arguments.length; i++) {
console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
arguments最常用的方式,是判断传入参数的个数,要把某个参数变为“可选”参数,就只能通过
arguments判断,然后重新调整参数并赋值。
ES6引入了rest参数,可以帮助我们获取多余的参数。
function foo(a, b, ...rest) { //rest参数只能写在最后,前面用...标识
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
foo(1); //参数没填满 为空数组 不是undefined
// 结果:
// a = 1
// b = undefined
// Array []
注意return
JavaScript引擎有一个在行末自动添加分号的机制。
function foo() { return { name: 'foo' }; } foo(); // undefined //当你这样写return,自动添加分号的机制该方法会变成 function foo() { return; // 自动添加了分号,相当于return undefined; { name: 'foo' }; // 这行语句已经没法执行到了 }
作用域
-
变量只在作用域内可以被引用,函数体内部声明变量,变量的作用于为这个函数的函数体
-
不同函数体内的同名变量各自独立,互不影响
-
一个函数的内部函数可以访问外部函数的变量,反之不行。像是流水,从高往低,反过来不行。
-
内部函数与外部函数的变量重名,内部变量将“屏蔽”外部变量
JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。
全局作用域
不在任何函数内定义的变量就具有全局作用域,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性
var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'
局部作用域
不同于Java,for循环等语句块中是无法定义局部作用域的变量的。ES6引入了新的关键字let,用let代替var可以申明一个局部作用域。
变量提升
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部。
function foo() {
var x = 'Hello, ' + y;
console.log(x);
var y = 'Bob';
}
//相当于
function foo() {
var y; // 提升变量y的申明,此时y为undefined
var x = 'Hello, ' + y;
console.log(x);
y = 'Bob';
}
JavaScript引擎自动提升了变量
y的声明,但不会提升变量y的赋值。请严格遵守“在函数内部首先申明所有变量”这一规则
常量
ES6引入了const关键字来定义常量,它具有块级作用域和let类似,和Java中的final关键字类似。
const PI = 3.14; //无法被修改
解构赋值
在ES6中,我们使用解构赋值可以使用这样的方式。
var [x, y, z] = ['hello', 'JavaScript', 'ES6']; // 把数组的各个值赋给各个变量。
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']]; //注意嵌套层次和位置要保持一致
let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
我们也可以对对象进行解构赋值
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school',
address: {
city: 'Beijing',
street: 'No.1 Road',
zipcode: '100001'
}
};
var {name, age, passport} = person;
var {name, address: {city, zip}} = person; //注意嵌套层次和位置要保持一致
如果对应的属性不存在,变量将被赋值为
undefined
当变量名和属性名不一致
// 把passport属性赋值给变量id:
let {name, passport:id} = person; // 注意: passport不是变量,而是为了让变量id获得passport属性:
解构赋值可以使用默认值
// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;
函数接受一个对象作为参数,使用解构赋值
function buildDate({year, month, day, hour=0, minute=0, second=0}) {
return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}
声明
文章为本人学习JS笔记,用于快速查找知识点以及总结