函数表达式

一、定义函数的方式

1.函数声明:function abc(){}

2.函数表达式:var abc = function(){}

二、递归

1.通过自身的名字调用:但函数名赋值给其他函数时失效

function factorial(num){
    if (num <= 1){
        return 1;
    } else {
        return num * factorial(num-1);
    }
}
View Code

2.通过arguments.callee调用:在严格模式下不能访问arguments.callee

function factorial(num){
    if (num <= 1){
        return 1;
    } else {
        return num * arguments.callee(num-1);
    }
}
View Code

3.创建一个f()函数

var factorial = (function f(num) {
    if (num <= 1){
        return 1;
    } else {
        return num * f(num-1);
    }
})
View Code

三、闭包

1.活动对象与变量对象

以function compare(value1, value2){}为例

全局变量对象为compare;活动对象为arguments、value1、value2;此时的活动对象也叫局部变量对象。

2.闭包的理解:

function a(value) {
    return function(value1, value2) {
        return 1;
    }
}
var abc = a();

abc为a函数的中的匿名函数,存在于全局变量中,则a的活动对象不会被删除,abc=null则活动对象才会被删除。

3.闭包与变量

function createFunctions(){
    var result = new Array();
    
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i;
        };
    }
    
    return result;
}
var a = createFunctions();

console.log(a[1]());

a = [function(){return i;}, function(){return i;},function(){return i;}...];

全局变量中引用createFunctions中的匿名函数,所以他的活动对象一直存在,且i=10。

function createFunctions(){
    var result = new Array();
    
    for (var i=0; i < 10; i++){
        result[i] = (function(num){
            return function() {
                return num;
            }
        })(i);
    }
    
    return result;
}
var a = createFunctions();

console.log(a[1]());

a = [function(){return 0;}, function(){return 1;},function(){return 2;}...];

使用该方法使其强制输出

4.关于this对象

在全局函数中,this等于window

var name = "The Window";

var object = {
    name : "My Object",

    getNameFunc : function(){
        return function(){
            return this.name;
        };
    }
};

console.log(object.getNameFunc()());//The Window 非严格模式下
View Code

此时的object.getNameFunc()处于全局中,this指向window

在对象中指向该对象

var name = "The Window";

var object = {
    name : "My Object",

    getNameFunc : function(){
        var that = this;
        return function(){
            return that.name;
        };
    }
};

console.log(object.getNameFunc()());//My Object
View Code

此时的object.getNameFunc()同样处于全局中,that为getNameFunc()的活动对象,可以引用,所以返回My Object。

this的指向发生改变

var name = "The Window";

var object = {
    name : "My Object",

    getName : function(){
        return this.name;
    }
};
console.log(object.getName());//My Object
console.log((object.getName)());//My Object
var abc = object.getName;
console.log(abc());//The Window
View Code

object.getName()与(object.getName)()的调用方式一样,在object中调用

而var abc = object.getName;时,该函数处于全局中

5.内存泄漏

function assignHandler() {
    var element = document.getElementById('div1');
    element.onclick = function() {
        console.log(element.id);
    }
}
assignHandler();
View Code

闭包作用域链中保存着一个HTML元素,则该元素不能被销毁alert保存着对assignHandler活动对象element的引用,每次调用element的数量会增加。

解决方法:

function assignHandler() {
    var element = document.getElementById('div1');
    var id = element.id;
    element.onclick = function() {
        console.log(id);
    }
    element = null;
}
assignHandler();
View Code

四、模仿块级作用域

没有块级作用域

for(var i = 0; i < 3; i++) {

}
var i;
alert(i);//3
View Code

模拟块级作用域

(function() {
    for(var i = 0; i < 3; i++) {

    }
})();
var i;
alert(i);
View Code

用在全局作用域中,避免添加过多的变量和函数

五、私有变量

1.通过构造函数返回

function myObject() {
    var privateVariable = 10;
    function privateVateFunction() {
        return privateVariable;
    }
    this.publicMethod = function() {
        privateVariable++;
        return privateVateFunction();
    }
}

var a = new myObject();
console.log(a.publicMethod());//11
var b = new myObject();
console.log(b.publicMethod());//11
View Code

2.通过全局变量返回(闭包) 

(function() {
    var privateVariable = 10;
    function privateVateFunction() {
        return privateVariable;
    }
    myObject = function() {}

    myObject.prototype.publicMethod = function() {
        privateVariable++;
        return privateVateFunction();
    }
})();

var a = new myObject();
console.log(a.publicMethod());//11
var b = new myObject();
console.log(b.publicMethod());//12
View Code

3.通过return返回方法(闭包) 

var aingleton = (function() {
    var privateVariable = 10;
    function privateVateFunction() {
        return privateVariable;
    }

    return {
        publicMethod : function() {
            privateVariable++;
            return privateVateFunction();
        }
    }
})();

console.log(aingleton.publicMethod());//11
console.log(aingleton.publicMethod());//12
View Code

4.通过return返回对象(闭包)

function CustomeType() {}

var aingleton = (function() {
    var privateVariable = 10;
    function privateVateFunction() {
        return privateVariable;
    }

    var object = new CustomeType();

    object.publicMethod = function() {
        privateVariable++;
        return privateVateFunction();
    }
    return object;
    
})();

console.log(aingleton.publicMethod());//11
console.log(aingleton.publicMethod());//12
View Code
原文地址:https://www.cnblogs.com/pcd12321/p/5585852.html