js闭包 一些题目

1.相关问题描述:到底该怎么去理解闭包?

代码片段A

复制代码
!function(){
    var num=1;
    var exp={};
    function add(num){
        return num++;
    } 
    exp.getAddNum=function(){
        return add(num);
    }
    window.a=exp;
}()

console.log(a.getAddNum()); // 1
console.log(a.getAddNum()); // 1
复制代码

 

代码片段B

复制代码
!function(){
    var num=1;
    var exp={};
    function add(){
        return num++;
    }
    exp.getAddNum=function(){
        return add();
    }
    window.a=exp;
}()

console.log(a.getAddNum());  // 1
console.log(a.getAddNum());  // 2
复制代码

 

解释:
第一个里面是你传递进去的,他会使用当前作用域接收到的这个形参的值,它并没有去改变外层num的值,因此你每次用它来传递,值都是1。
而第二个的'add'方法中并没有num变量,他会通过作用域链找到外层的num,那么你这样调用时每次都是操作的外层变量的值,而这个值在你return之后是会累加的。
关于上下文和作用域链你可以看看这篇文章
图解Javascript上下文与作用域 :http://blog.rainy.im/2015/07/04/scope-chain-and-prototype-chain-in-js/

2.javascript关于闭包的面试题

复制代码
function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000
  
复制代码

 

问:
在这段代码中,result()它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。为什么会这样呢?尤其是第二次,为何输出的不是999呢?
nAdd=function(){n+=1}又起到了什么作用呢?

解释:

首先f1 函数的作用域链。1 指向全局,2 指向自身。自身里面包括,n=999 f2, nAdd这个函数没有加var声明,是全局变量。但是里面的n引用的是f1内部的n=999

然后 f2函数的作用域链。1 指向全局 2 指向f1的作用域 3,指向自己作用域

nAdd这个作用域链 1 指向全局,2 持有n=999引用,(我觉得也指向f1作用域),3 指向自己作用域

执行 var result=f1(); 这个楼主应该清楚,就是result就是指向f2函数
调用 result();弹出n.就是先去自己作用域找。没有。然后就去上级作用域f1里找。找到了。n=999,弹出999
执行nAdd(),这时,去自己作用域里找。没有n,所以去上级作用域。f1里。发现n,执行n=n+1,n变1000
再次执行result();和上一次一样。就是先去自己作用域找。没有。然后就去上级作用域f1里找。找到了 这时n=1000了。所以弹出1000

3.[] 和 Array 调用 slice 方法引起的问题

问题表示:在某些场景下,需要将函数的 arguments 参数作为一个数组调用,但是 arguments 是一个奇异对象,所以试着将 arguments 转化为一个数组;

function argToArr(){
    return [].slice.call(arguments, 0);
}
console.log(argToArr(1,2,3));    //[1,2,3]

 

function argToArr(){
        return Array.slice.call(arguments, 0);
    }
    console.log(argToArr(1,2,3));    //[]

问:这是为什么呢?
另外还有一个问题,是关于 Array 是怎么找到 slice 方法的?
Array 本身是没有 slice 方法,它的方法在 Array.prototype 中,而我们在调用 slice 方法的时候,如果在 Array 本身没有找到 slice 方法的话,会通过它的原型链往上查找,而 Array.proto 并没有指向 Array.prototype,而是指向 Function(),那么它是怎么找到 slice 方法的呢?

解释:

第二段代码报错是因为Array是构造函数不是对象,打开控制台,输入 typeof Array,结果是 function
你也说了slice()方法在其原型对象中,而[]就是Array的原型对象,在控制台中输入 Array.prototype,结果是[],所以第一段代码可以顺利执行。

第二段代码如下修改就可以了:

functionargToArr(){
    returnArray.prototype.slice.call(arguments, 0); // 改这一行
}
console.log(argToArr(1,2,3)); 

其实你的本质问题就在于误认为Array是数组对象,然而它是构造函数。

4.预解析相关

复制代码
myname = "global"; // 全局变量
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();
复制代码

在这个例子中,你可能会以为第一个alert弹出的是”global”,第二个弹出”loacl”。这种期许是可以理解的,因为在第一个alert 的时候,myname未声明,此时函数肯定很自然而然地看全局变量myname,但是,实际上并不是这么工作的。第一个alert会弹 出”undefined”是因为myname被当做了函数的局部变量(尽管是之后声明的),所有的变量声明当被悬置到函数的顶部了。因此,为了避免这种混 乱,最好是预先声明你想使用的全部变量。

上面的代码片段执行的行为可能就像下面这样:

复制代码
myname = "global"; // global variable
function func() {
   var myname; // 等同于 -> var myname = undefined;
   alert(myname); // "undefined"
   myname = "local";
   alert(myname); // "local"}
func();
复制代码
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页