JavaScript函数
函数的定义和调用
function f1 (a,b) {
if (a > b) {
return a;
} else {
return b;
}
}
上述的函数 f1
定义如下:
- function 关键字定义函数
(a,b)
是函数的名称{}
之间的代码是函数体,可以包含若干语句,也可以没有任何语句 注意:函数在遇到return
时,就执行完毕,返回一个返回值。
JavaScript函数也是一个对象,因此上面定义的函数f1()
也是一个函数对象,所以也可以通过下面的这种方式定义函数:
let f2 = function (a,b) {
if (a > b) {
return a;
} else {
return b;}}
f2(4,5);//4
调用函数
按照顺序传入参数即可。此外,由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没问题。
f1(4,5,6,7,);//返回5;
变量的作用域
在JavaScript中声明的变量是有作用域的,如果一个变量在函数体内部申明,则这个变量的作用域为这个函数体,在函数外部不可以引用这个变量。
function f1() {
let a = 10;
a += 1;
}
a += 2; // Uncaught ReferenceError
- 不同函数内部的同名变量互相独立,互不影响
- JavaScript中的函数可以嵌套,内部函数可以访问外部函数的变量,反之则不行。
- 如果内部函数定义了和外部函数同名的变量,则内部函数的变量将替代外部函数变量。
全局作用域
不在任何函数上定义的变量就具有全局作用域,实际上JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性。
let a = 'cococo';
alert(a);
alert(window.a);
直接访问变量 a
和访问 window.a
是一样的。所以以变量的方式let f1 = function(){}
定义的函数实际上也是一个全局变量,并绑定到window
对象。
解构赋值
从ES6开始,JavaScript引入解构赋值,可以同时对一组变量赋值。
let [a1,a2,a3] = ['你好','我是','Nick'];
如果需要从一个对象中取出若干属性,也可以使用解构赋值,快速获取对象的指定属性。 使用解构赋值可以大大简化代码
let x =1,y = 2;
[x,y] = [y,x];
交换x和y的值
方法
在一个对象中绑定函数,这个函数称作方法。
let Nick = {
name:'Nick',
birth:1990,
age: function() {
let y = new Date().getFullYear();
return y - this.birth;
}
};
Nick.age; // function Nick.age()
Nick.age(); //31
绑定到对象的函数叫做方法,但是它的内部使用了一个 this
关键字。在一个方法内部, this
是一个特殊的变量,它始终指向当前对象,也就是 Nick
这个变量,所以this.birth
可以拿到 Nick
的 birth
属性。
但是如果把这个对象分开来写:
function getAge() {
let y = new Date().getFullYear();
return y - this.birth;
}
let Nick = {
name:'Nick',
birth:1990,
};
Nick.age();//31,正常结果
getAge(); //NaN
为什么单独调用getAge()
返回了 NaN
?
JavaScript的内部函数如果调用了 this
,那么这个this指向谁?
- 如果以对象的方法形式调用,比如
Nick.age()
,这个函数的this
指向被调用的对象,也就是Nick
- 如果单独调用函数,如
getAge()
,此函数就会指向全局对象,也就是window
高阶函数
JavaScript函数实际上都指向某个变量,既然变量可以指向函数,函数的参数就能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就是高阶函数。
一个简单的高阶函数:
function add(x,y,z) {
return f(x) + f(y);
}
Array.map()
map()
方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
funcion pow(x) {
return x * x;
}
let arr = [1,2,3,4,5];
let result = arr.map(pow);// [1,4,9,16,25]
Array.reduce()
reduce()
方法对数组中的每个元素执行一个由你educer函数(升序执行),将其结果汇总为单个返回值。
- reduce实现一个数组求和。
let arr = [1,3,5,7,9];
arr.reduce(function (x,y) {
return x + y;
}); //25
reduce
计算数组中每个元素出现的次数
let names = ['Alice','Nick','Bob','Alice','Bob','Bruce'];
let countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
},{});
//countedNames :{Alice: 2, Nick: 1, Bob: 2, Bruce: 1}
Array.filter()
Array.filter()
创建一个新的数组,里面包含通过筛选条件的元素。与 map()
类似的是 filter()
也接受一个函数,但是不同的是 filter()
把传入的函数一次作用于每个函数,根据返回值 true
还是 false
来决定保留还是丢弃。
保留奇数:
let arr = [2,3,23,5,6,68,32,97];
let arr1 = arr.filter(function(x) {
return x % 2 != 0
});
Array.sort()
sort()
方法用原地算法对数组进行排序,并返回数组。默认排序顺序是将元素转换为字符串,再根据他们的UTF-16代码单元值序列。
- 按照数字大小排序
let arr = [12,2,5,454,1,78];
arr.sort(function (x,y) {
if(x<y) {
return -1;
}
if(x>y) {
return 1;;
}
return 0;
});
console.log(arr); // [1,2,5,12,78,454]
//
let arr2 = [2,5,6,2,6,7,8,23,43];
arr.sort(function (a,b) {
return a - b;
});
arr2;//[2, 3, 5, 6, 23, 32, 68, 97]
箭头函数
let fn = x => x * x;
相当于:
function(x) {
return x * x;
}
如果不止有一个参数,需要括号括起来。
(x,y) => x + y;
如果需要返回一个对象,因为和函数体的语法有冲突,需要这样写:
`x => ({ fo: x});