- 函数分类
本质上,函数就一种,为了好理解,人为的分为两种。函数是一种特殊的对象,它是引用数据类型,存储在堆中,并且一个函数有两块内存,一块表示函数本身,另外一块表示原型。
1. 普通函数
为了封装特定功能的代码,比如排序方法
为了区分构造函数,普通函数的函数名首字母小写的。
一般使用"()"来调用普通函数,例如 parseInt()
function sort(array){
return 排好序的arry
}
2. 构造函数
为了实例化对象,并且为对象提供的公共的方法【对象可以调用其构造函数原型中的方法】
为了区分普通函数,构造函数的函数名首字母大写的
一般使用new关键字来调用构造函数。例如 var obj = new Object();
- 函数定义
1. 函数声明
function 函数名(形参){
方法体
return 返回值
}
例如
add(1,3);
function add(a,b){
var total = a + b;
return total;
}
函数声明会被提升。
2. 函数表达式
var a = {};
var 函数名 = function(){};
例如:
add();
var add = function(a,b){return a+b};
在函数声明之前无法调用函数,因为var声明的变量会提升,undefined()就会报错。
- 函数调用
3. function add(a,b){
console.log(this);
return a +b;
}
1. 函数名(实参列表) 一般用于调用普通函数
add(1,2);
2. new 函数名(实参列表) 一般用于调用构造函数,创建实例对象
new add(1,2);
3. 函数名.call(this,实参列表)
this表示为当前调用的函数中的this赋值
add.call({},1,2)
4. 函数名.apply(this,实参数组)
this表示为当前调用的函数中的this赋值
add.apply("a",[1,2])
- 函数内部属性
只有在函数内部才能访问的属性并且只有在函数调用的时候才能确定其值的属性。
arguments
本质上是一个类数组对象,该对象在函数执行的时候可以将用户传递的实参进行保存。
{
"0":"terry",
"1":"larry",
"2":"tom",
length:3,
callee
}
argument.callee指向当前函数。callee无法在严格模式下使用
this
this指向当前执行环境的对象。同一个函数中的this的取值跟调用方法有关,调用方法不同this可能就不同。
判断技巧:
如果使用括号调用,查看括号前面是不是函数,如果是,继续查看函数前有没有点,如果有点,this为点前面的变量
例如:
function foo(){
console.log(this);
}
foo(); foo中的this指向全局环境对象,window/global
obj.foo(); foo中的this指向obj
[1,2,3,foo,4][3]() foo中的this指向数组
执行环境{
全局执行环境
浏览器 window
nodejs global
方法内部执行环境
this
}
- 函数作用域
在一个函数中,通过var声明的变量没有局部作用域。
如何在一个函数中使用var声明一个变量,该变量为局部作用域
(function(){
var a = 3; // a只能在刚方法中生效,模拟局部作用域
})();
1. var声明的变量
全局作用域
方法作用域:方法内部声明的变量在方法执行完毕后释放,方法外部不可以访问
2. let声明的变量
全局作用域
方法作用域:方法内部声明的变量在方法执行完毕后释放,方法外部不可以访问
局部作用域:仅在当前代码块中有效
- 函数作为参数(回调函数)
问题:具有一个数组,我们想要迭代它,但是我们又不会使用循环语句,你能否提供一个方法myForeach,来帮我们进行遍历。
Array.prototype.myForeach = function(handler){
// 遍历arr ,this
for(var i=0;i<this.length;i++){
// 回调
handler(this[i])
}
}
var arr = ["terry","larry","tom"];
arr.myForeach( function(item){
console.log(item);
} )
- 函数作为返回值
function foo(){
return function(){
console.log("hello world");
}
}
foo()();
- 闭包
在一个函数中嵌套了一个函数,子函数引用了外部函数的变量。子函数与外部函数的变量就组成了闭包。
function foo(){
var i = 3;
setTimeout(function(){
console.log(i);
},1000);
i++;
}
foo();
console.log("end...");