画重点:js中函数是个对象;而函数名为栈中的指针指向堆中的函数对象
1:普通函数(函数声明):
函数声明总是以function关键词开始,反之为函数表达式
function obj(a,b){
return a+b;
}
obj(1,2);//3
或
([3,4]).reduce(obj);//7
console.log(([1,2]).reduce(obj,10));//13
划重点:
- 函数声明在当前作用域内创建了一个变量,其除了可以当做普通函数调用之外,还用于递归或者分离的事件监听。
- 函数表达式和箭头函数是无法创建并绑定函数名称作为函数变量。
- 函数提升仅适用于函数声明,而不适用于函数表达式.
- 函数声明可以被递归,就是说函数可以调用其本身。
reduce()
:方法將一個累加器及陣列中每項元素(由左至右)傳入回调函数,將陣列化為單一值。
递归小知识:
调用自身的函数我们称之为递归函数。在某种意义上说,递归近似于循环。两者都重复执行相同的代码,并且两者都需要一个终止条件(避免无限循环或者无限递归)。
一个函数可以指向并调用自身。有三种方法可以达到这个目的:
- 函数名
arguments.callee
- 作用域下的一个指向该函数的变量名
小列子:
function obj(x) {
if (x<=0) // "x<=0" 是退出条件(等同于 "!(x>0)")
return;
// 做些什么
obj(x -1); // 递归调用
}
obj(10);
2:函数表达式
函数表达式:以var开始
var obj = function(o){
alert(o);
}
函数表达式:map()的参数
var obj = ([1,2,3]).map(function(x){
return x>1
})
console.log(obj);//(3) [false, true, true]
函数表达式:自执行函数
(function obj(mss){
return console.log(mss*2)
})(5);//10
函数表达式:{}
var obj = {
arr:[3,2,1],
num:function(){
return this.arr.map(function(x){
return x>2
})
}
}
console.log(obj.num());//(3) [true, false, false]
- num:function(){}:在num对象上创建一个方法
- .map(function(x){}):当做一个方法函数
3:匿名函数
a:变量匿名函数:当函数中没有名称(名称和属性是一个空字符串)时,这个函数是一个匿名函数。
var obj = function(age){
return age
}
obj.name//''
obj就是一个匿名函数,其obj.age的值为' '(空)。
b:命名函数表达式:当表达式中指定了一个名称时。
var getType = function funName(a) {
console.log(typeof funName === 'function'); //true
return typeof a;
}
console.log(getType('1')); // 'string'
console.log(getType); // ƒ funName(variable) {
//console.log(typeof funName === 'function');
//return typeof variable;
//}
console.log(typeof funName === 'function'); //false
console.log(getType('1')); // 'string'
console.log(getType.name);//funName
function funName(a) { }为命名函数表达式。在函数作用域内存了一个funName变量。所以getType.name中的name属性就是函数的名称funName
4:嵌套函數
function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2, 3); // returns 13
b = addSquares(3, 4); // returns 25
c = addSquares(4, 5); // returns 41
5:箭头函数
function Person(){
this.age = 0;
setInterval(() => {
this.age++;
console.log(this.age);
}, 1000);
}
var p = new Person();
结果为:
6:方法定义可以在object literals和ES6 class时定义。
a:class定义
class Name {
constructor(age){
this.age = age;
}
nameObj(name){
return `${name} is ${this.age}`
}
}
var names = new Name('18');
console.log(names.nameObj('Livia') );//Livia is 18
在构造器中填入Name函数传递过来的参数;实例化函数(new就是实例化函数)
b:object literals定义
var nameType ={
arr:[],
addName(...name){
this.arr.push(...name);
},
getName(idx){
return console.log(this.arr[idx],this.arr)//Nemo (3) ["Livia", "Tony", "Nemo"]
}
}
nameType.addName('Livia','Tony','Nemo');
nameType.getName(2);
addName()和getName()方法在nameType对象使用方法定义。这些方法可以向这样调用nameType.addName()
传统方法定义和属性定义,是getName: function() {}这样定义的。
var getType = function(a) {
return {
getName: function() {
return a;
}
}
};
var getname = getType('1')
console.log(getname.getName()); //1
参考: