首页 > 代码库 > 重温Javascript(四)-函数

重温Javascript(四)-函数

函数


 

  函数声明提升,在执行代码之前会先读取函数声明

sayHi();function sayHi(){    alert("Hi!");}

 

递归


 

  arguments.callee是指向正在执行的函数的指针

  还可以换种方式达成一样的效果

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

 

 

函数执行的作用域链


 

function compare(value1, value2){    if (value1 < value2){        return -1;    } else if (value1 > value2){        return 1;    } else {        return 0;    }}var result = compare(5, 10);

技术分享

  先定义了compare()函数,又在全局作用域调用它。当调用时,会创建一个包含arguments、value1、value2的活动对象。全局执行环境的变量对象(包含result和compare)在compare()执行环境的作用域中处于第二位

  作用域链本质上是一个指向变量对象的指针列表,只引用但不实际包含变量对象

  

  

闭包


 

  闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,在一个函数内部创建另一个函数  

function createComparisonFunction(propertyName) {    return function(object1, object2){        var value1 = object1[propertyName];        var value2 = object2[propertyName];        if (value1 < value2){            return -1;        } else if (value1 > value2){            return 1;        } else {            return 0;        }    };}
var compare = createComparisonFunction("name");var result = compare({ name: "Nicholas" }, { name: "Greg" });

技术分享

  

  在匿名函数从 createComparisonFunction()中被返回后,它的作用域链被初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。这样,匿名函数就可以访问在createComparisonFunction()中定义的所有变量。createComparisonFunction()

函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。换句话说,当createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中;直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁

//创建函数var compareNames = createComparisonFunction("name");//调用函数var result = compareNames({ name: "Nicholas" }, { name: "Greg" });//解除对匿名函数的引用(以便释放内存)compareNames = null;

  创建的比较函数被保存在变量compareNames 中。而通过将compareNames 设置为等于null解除该函数的引用,就等于通知垃圾回收例程将其清除。随着匿名函数的作用域链被销毁,其他作用域(除了全局作用域)也都可以安全地销毁了。

  

闭包与变量


 

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

  每个函数都返回10。因为每个函数的作用域链中都保存着createFunctions() 函数的活动对象, 所以它们引用的都是同一个变量i 。

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

 

闭包与this,arguments


 

  每个函数在被调用时都会自动取得2个特殊变量:this和arguments。内部函数在搜索这2个变量时,只会搜索到其活动对象为止,不能直接访问外部函数中的这2个变量。把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以访问了。arguments也是如此。

var name = "The Window";var object = {    name : "My Object",    getNameFunc : function(){        var that = this;        return function(){            return that.name;        };    }};alert(object.getNameFunc()()); //"My Object"    

 

模仿块级作用域


 

function outputNumbers(count){    for (var i=0; i < count; i++){        alert(i);    }    alert(i); //计数}

  通常称为私有作用域  

(function(){    //这里是块级作用域})();
function outputNumbers(count){    (function () {        for (var i=0; i < count; i++){            alert(i);        }    })();    alert(i); //导致一个错误!}

 

私有变量


  

function MyObject(){    //私有变量和私有函数    var privateVariable = 10;    function privateFunction(){        return false;    }    //特权方法    this.publicMethod = function (){        privateVariable++;        return privateFunction();    };}
function Person(name){    this.getName = function(){    return name;};    this.setName = function (value) {        name = value;    };}var person = new Person("Nicholas");alert(person.getName()); //"Nicholas"person.setName("Greg");alert(person.getName()); //"Greg"

  

静态私有变量


 

  

(function(){    //私有变量和私有函数    var privateVariable = 10;    function privateFunction(){        return false;    }    //构造函数    MyObject = function(){    };    //公有/特权方法    MyObject.prototype.publicMethod = function(){        privateVariable++;        return privateFunction();    };})();

  未经声明的变量,会创建一个全局变量

  但使用prototype的问题时实例变量需要自己定义

  

(function(){    var name = "";    Person = function(value){        name = value;    };    Person.prototype.getName = function(){        return name;    };    Person.prototype.setName = function (value){        name = value;    };})();var person1 = new Person("Nicholas");alert(person1.getName()); //"Nicholas"person1.setName("Greg");alert(person1.getName()); //"Greg"var person2 = new Person("Michael");alert(person1.getName()); //"Michael"alert(person2.getName()); //"Michael"

 

模块模式


  单例对象  

var singleton = {    name : value,    method : function () {    //这里是方法的代码    }};

  模块模式通过为单例添加私有变量和特权方法使其得到增强

var singleton = function(){    //私有变量和私有函数    var privateVariable = 10;    function privateFunction(){        return false;    }    //特权/公有方法和属性    return {        publicProperty: true,        publicMethod : function(){            privateVariable++;            return privateFunction();        }    };}();

  以这种模式创建的每个单例都是Object的实例,因为最终要通过一个对象字面量来表示它。单例通常作为全局对象存在,不会将它传递给一个函数,不会使用instanceOf来检查其对象类型

 

增强的模块模式


 

  在返回对象之前加入对其增强的代码。适合的场景是单例必须是某种类型的实例,还必须添加某些属性或方法对其增强。

var singleton = function(){    //私有变量和私有函数    var privateVariable = 10;    function privateFunction(){        return false;    }    //创建对象    var object = new CustomType();    //添加特权/公有属性和方法    object.publicProperty = true;    object.publicMethod = function(){        privateVariable++;        return privateFunction();    };    //返回这个对象    return object;}();

 

引用:

《JavaScript高级程序设计中文版》

重温Javascript(四)-函数