发布于 2015-12-20 02:57:50 | 249 次阅读 | 评论: 0 | 来源: PHPERZ

这里有新鲜出炉的Javascript教程,程序狗速度看过来!

JavaScript客户端脚本语言

Javascript 是一种由Netscape的LiveScript发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如Perl,遗留的速度问题,为客户提供更流畅的浏览效果。


对于以下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之后是会累加的。
 

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();

为了完整,我们再提一提执行层面的稍微复杂点的东西。代码处理分两个阶段,第一阶段是变量,函数声明,以及正常格式的参数创建,这是一个解析和进入上下文 的阶段。第二个阶段是代码执行,函数表达式和不合格的标识符(为声明的变量)被创建。但是,出于实用的目的,我们就采用了”hoisting”这个概念, 这种ECMAScript标准中并未定义,通常用来描述行为。



最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务