最近有几道前端面试题在网上非常流行,来看看它们都是什么:

题1. 写出下面程序执行结果?

<script type="text/javascript">
  var b, c=null, d=1;
  alert(a);
  alert(b);
  alert(c);
  alert(d);
</script>

解析: 在javascript中,要使用一个变量,首先要声明变量,再给变量指定初始值。变量是用var来声明,如果一个变量声明了,但没有指定初始值,那么该变量的默认初始值是undefined。所以在函数中,因为a没有声明,故会报错。b声明了,但是没有指定初始值,所以是undefined。c和d都声明了并指定了初始值,则弹出对应的值。

<script type="text/javascript">
  var b, c=null, d=1;
  alert(a); //报错 ,提示 a 未定义
  alert(b); //undefined
  alert(c); //null;
  alert(d); //1;
</script>

题2. 求出y和z的值是多少?

<script type="text/javascript">
  var x = 1, y = 0, z = 0;
  function add(n){n=n+1;}
  y = add(x);
  function add(n){n=n+3;}
  z = add(x);
  alert(y);
  alert(z);
</script>

解析:因为最后的alert函数都要求用到函数的返回值,但是两个函数都没有返回值,所以都弹出 undefined。另外,如果函数有返回值的话,y的结果是4,z的结果也是4。因为函数名相同,后面的函数会覆盖前面的函数,所以都弹出4。

<script type="text/javascript">
  var x = 1, y = 0, z = 0;
  function add(n){n=n+1;}
  y = add(x);
  function add(n){n=n+3;}
  z = add(x);
  alert(y); //undefined 因为没有返回值
  alert(z); //undefined 因为没有返回值
// 如果函数中有return , 则y和z都是4 因为y和z都是调用的最后一个函数
</script>

题3. 说说form中input的readonly和disable,两者有什么区别?

解析:readonly使得input的value值只读,但该值可以选择和复制;并且该值也可以传递给后台

disable也是使得input的value值只读,但该值不能复制,不能选择;值不可以传递给后台

题4. 写一个正则表达式,判断字符串是否是这样组成的,第一个必须是字母,后面可是的字母、数字下划线,总长度为5-10?

解析:re=/^[a-zA-Z]{1}\w{4,9}/g 是这个吗?

实践是检验真理的唯一标准,下面我们来用个实例验证下:

<input type="text" id="txt"/>
<input type="button" value="test" id="btn"/>

<script type="text/javascript">
var oTxt=document.getElementById("txt"),oBtn=document.getElementById("btn"),re=/^[a-zA-Z]{1}\w{4,9}/g;
  oBtn.onclick=function(){
    if(re.test(oTxt.value)){
      alert("match")
    }
    else{
      alert("not match!")
    }
  }
</script>

经过验证,我们发现当输入6个字母时,第一次点击按钮弹出“match”,第二次点击按钮弹出”not match!”,再次点击按钮弹出“match”,再次点击按钮弹出“not match!”……

为什么会这样呢?这是因为这里使用全局匹配 g

RegExp对象 是保存有关正则表达式模式匹配信息的固有全局对象。 不要将 全局RegExp对象 与 正则表达式 对象混淆。尽管听起来像是一回事,但它们是截然不同的。全局RegExp对象 的属性包含不断更新的关于每个匹配出现的信息,而正则表达式对象只包含出现正则表达式匹配的信息。

全局RegExp对象 有一些属性,比如index、lastIndex、lastMatch、$1 – $9 等,虽然它们不能直接被查询,但会在匹配中不断被改变。

上面的这个例子,就是因为 index 被改变的的原因:
第一次搜索到了字符串的第5个字符,找到了匹配,所以返回了真。
第二次搜索会从第6个字符开始,一直搜索到末尾,找不到匹配,所以返回了假。
由于第二次搜索到了末尾,第三次搜索会从第1个字符开始,找到了匹配,所以返回了真。
第四次搜索的情况和第二次是一样的。

总结一下,全局RegExp对象 远比你想的要复杂,它有很多你不知道的属性在随着匹配而不断改变,而这些属性是很可能影响下一次的匹配结果的。
所以,除非你清楚自己在干什么,否则还是用纯粹的正则表达式更安全。

因此,正确的正则是:re=/^[a-zA-Z]{1}\w{4,9}/;

题5. 说出下列函数的运行结果?

function test1(){
  var a = 10;
  function test(){
    alert(a);
    var a = 5;
  }
  test();
  alert(a);
}
test1();

function test2(){
  var a = 10;
  function test(){
    alert(a);
    a = 5;
  }
  test();
  alert(a);
}
test2();

解析:在函数体内,局部变量的优先级要高于同名的全局变量。

你可能会误以为alert(a)的值是5或者10,其实都不是。

因为代码还没有执行到函数test中a=5的地方,但是由于函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,在函数体内局部变量覆盖了同名全局变量。尽管如此,只有在程序执行到a=5的地方,局部变量才会被真正赋值,在问题一我们也知道,变量只声明未赋值的初始值是undefined。故alert(a)为undefined。而test函数外面的alert(a)的值是弹出全局变量 10。

假如:test函数中执行alert(a)之前没有变量,如果去掉var a=5, 则结果为10 ; 如果把var a=5 放在aler(a)前面,则弹出5。

function test1(){
  var a = 10;
  function test(){
    alert(a);
    var a = 5;
  }
  test(); //undefined
  alert(a); //全局变量 结果为 10
}
test1();

因为下面的函数两个a都是全局变量了,依照前一个函数的解释,函数test里面的alert(a)的值自然是10。然后全局变量被a=5覆盖,于是,test函数外面的alert(a)的值是5。

假如:如果a=5在函数test的alert(a)前面,则结果是5,因为就近原则。

function test2(){
  var a = 10;
  function test(){
    alert(a);
    a = 5;
  }
  test(); //10
  alert(a); //5 ,a=5变为全局变量覆盖了原来的a=10
}
test2();