一、定义函数的方式
1.函数声明:function abc(){}
2.函数表达式:var abc = function(){}
二、递归
1.通过自身的名字调用:但函数名赋值给其他函数时失效
function factorial(num){ if (num <= 1){ return 1; } else { return num * factorial(num-1); } }
2.通过arguments.callee调用:在严格模式下不能访问arguments.callee
function factorial(num){ if (num <= 1){ return 1; } else { return num * arguments.callee(num-1); } }
3.创建一个f()函数
var factorial = (function f(num) { if (num <= 1){ return 1; } else { return num * f(num-1); } })
三、闭包
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 非严格模式下
此时的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
此时的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
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();
闭包作用域链中保存着一个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();
四、模仿块级作用域
没有块级作用域
for(var i = 0; i < 3; i++) { } var i; alert(i);//3
模拟块级作用域
(function() { for(var i = 0; i < 3; i++) { } })(); var i; alert(i);
用在全局作用域中,避免添加过多的变量和函数
五、私有变量
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
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
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
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