1.递归
递归函数在应用中不少见,结合之前介绍过的函数指针的作用,看一下下面的代码,会不会出错?
// 经典递归函数 function fun(num) { if(num <= 1) { return 1; } else { return num * fun(num - 1); } } // 将函数指针复制给一个变量 const newFun = fun; // 将原函数指针设置为null,就只有一个函数指针指向fun函数对象 fun = null; newFun(4); // 报错了,这是因为在fun()函数体中的fun函数找不到了
现在解决这种函数名字紧耦合的问题,可以使用arguments.callee函数指针,它是指向当前正在执行的函数。
(1)解决方法一:(这种方式在严格模式下会报错!)
// 可以将上面的代码修改为下面这样 function fun(num) { if(num <= 1) { return 1; } else { return num * arguments.callee(num - 1); } } // 这样就永远都会指向当前正在执行的函数,解决函数名耦合的为题
今天看到了另一种解决方式,可以使用函数表达式进行解决。
(2)解决方法二:(这种方式在严格模式和费严格模式下都可行)
var newFun = function f(num) { if(num <= 1) { return 1; } else { return num * f(num - 1); } } newFun(4); // 24
2.对this的值得理解
今天看到一句话,就是匿名函数的this对象具有全局性,前提是对this对象未做任何处理。
let name = "cs"; let obj = { name: "css", getName: function() { return this.name; } } console.log(this.name); // "css",this对象指向obj对象 // this对象在匿名函数中 let obj = { name: "css", getName: function() { return function() { return this.name; // 在匿名函数中返回值 } } } const nameValue = obj.getName()(); // 使得匿名函数自执行 console.log(nameValue); // "cs",这里的this指向了全局对象window,即window.name
也可以通过this对象的赋值进行维持this所指对象的存在。
let name = "cs"; let obj = { name: "css", getName: function() { let that = this; // 将this进行暂存 return function() { return that.name; } } } const nameValue = obj.getName()(); // "css",即使是定义在匿名函数中,但是this的值通过that进 行了维持,在外面依然可以通过this访问到obj对象 console.log(nameValue); // "css",this对象指向obj对象
3.模仿块级作用域
在js中是没有块级作用域这一概念的,但是我么可以通过匿名函数的方式创建块级作用域,这样做的好处是匿名函数中的变量都是私有变量,而不会破坏全局变量的执行。并且匿名函数在执行完毕时,就会将其函数体中的变量自动销毁,节省了内存空间。
function fun() { (function() { for(var i = 0; i < 10; i++) { alert(i); } })() alert(i); // 这里会对i变量进行报错,因为i在匿名函数执行结束后就销毁了 }
4.闭包的作用
闭包可以作为特权函数,在函数外部访问函数中的私有变量、局部变量和函数。
下面是通过构造函数创建的测试示例:
function Sum(a) { // 创建下面的两个闭包函数 this.closureOne = function() { return a; } this.closureTwo = function(val) { a = val; } } var sum = new Sum(10); // 在函数外部进行访问函数内部的私有变量 console.log(sum.closureOne()); // "10" // 在函数外部通过闭包函数对函数的私有变量进行操作 sum.closureTwo(20); console.log(sum.closureOne()); // "20"
网友评论