js中的一些面试题

js的基础知识灵活运用

在我们面试时经常会遇到一些很基本的题,到并我们能百分百答对,一部分原因是在工作中我们并不会这样写代码,还有就是基础知识不扎实,所以为了让自己面试的成功率提高,我们就要在提高的同时,不要忽视基础



function Foo() {

getName = function () { alert (1); };

return this;

}

Foo.getName = function () { alert (2);};

Foo.prototype.getName = function () { alert (3);};

var getName = function () { alert (4);};

function getName() { alert (5);}





//请写出以下输出结果:

Foo.getName();

getName();

Foo().getName();

getName();

new Foo.getName();

new Foo().getName();

new new Foo().getName();

这个是在网上找的一些面试题,虽然看着简单,不过想要做对还是要下一番功夫的


//答案:

Foo.getName();//2

getName();//4

Foo().getName();//1

getName();//1

new Foo.getName();//2

new Foo().getName();//3

new new Foo().getName();//3

我们一步一步来看:

第一问:


首先定义了一个叫Foo的函数,之后为Foo创建了一个叫getName的静态属性存储了一个匿名函数,之后为Foo的原型对象新创建了一个叫getName的匿名函数。之后又通过函数变量表达式创建了一个getName的函数,最后再声明一个叫getName函数。


第一问的 Foo.getName 自然是访问Foo函数上存储的静态属性,自然是2,没什么可说的。

第二问:


在这里我们可以把代码按照实际的解读顺序改写一下,改写如下


function Foo() {
getName = function () { alert (1); };
return this;
}
var getName;//只提升变量声明
function getName() { alert (5);}//提升函数声明,覆盖var的声明

Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明

getName();//最终输出4


第三问:


先执行了Foo函数,然后调用Foo函数的返回值对象的getName属性函数。
Foo函数的第一句 getName = function () { alert (1); }; 是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为 function(){alert(1)}。
注意:此处若依然没有找到会一直向上查找到window对象,若window对象中也没有getName属性,就在window对象中创建一个getName变量。
Foo函数返回的是window对象,相当于执行 window.getName() ,而window中的getName已经被修改为alert(1),所以最终会输出1

第四问:


直接调用getName函数,相当于 window.getName() ,因为这个变量已经被Foo函数执行时修改了,遂结果与第三问相同,为1

第五问:


此处考察的是js的运算符优先级问题。

可以在这里看 运算符优先级 ,通过查上表可以得知点(.)的优先级高于new操作,于是就可以这样理解:

new (Foo.getName)();

所以实际上将getName函数作为了构造函数来执行,遂弹出2。

第六问:


第六问首先看运算符优先级括号高于new,实际执行为

(new Foo()).getName()

遂先执行Foo函数,Foo构造函数中没有为实例化对象添加任何属性,遂到当前对象的原型对象(prototype)中寻找getName,最终输出3

第七问


同样是运算符优先级问题。最终实际执行为:

new ((new Foo()).getName)();

先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new。
遂最终结果为3
Contents
  1. 1. js的基础知识灵活运用
    1. 1.1. 在我们面试时经常会遇到一些很基本的题,到并我们能百分百答对,一部分原因是在工作中我们并不会这样写代码,还有就是基础知识不扎实,所以为了让自己面试的成功率提高,我们就要在提高的同时,不要忽视基础
      1. 1.1.1. 这个是在网上找的一些面试题,虽然看着简单,不过想要做对还是要下一番功夫的
      2. 1.1.2. 我们一步一步来看:
      3. 1.1.3. 第一问:
        1. 1.1.3.1. 首先定义了一个叫Foo的函数,之后为Foo创建了一个叫getName的静态属性存储了一个匿名函数,之后为Foo的原型对象新创建了一个叫getName的匿名函数。之后又通过函数变量表达式创建了一个getName的函数,最后再声明一个叫getName函数。第一问的 Foo.getName 自然是访问Foo函数上存储的静态属性,自然是2,没什么可说的。
      4. 1.1.4. 第二问:
        1. 1.1.4.1. 在这里我们可以把代码按照实际的解读顺序改写一下,改写如下
      5. 1.1.5. 第三问:
        1. 1.1.5.1. 先执行了Foo函数,然后调用Foo函数的返回值对象的getName属性函数。Foo函数的第一句 getName = function () { alert (1); }; 是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为 function(){alert(1)}。注意:此处若依然没有找到会一直向上查找到window对象,若window对象中也没有getName属性,就在window对象中创建一个getName变量。Foo函数返回的是window对象,相当于执行 window.getName() ,而window中的getName已经被修改为alert(1),所以最终会输出1
      6. 1.1.6. 第四问:
        1. 1.1.6.1. 直接调用getName函数,相当于 window.getName() ,因为这个变量已经被Foo函数执行时修改了,遂结果与第三问相同,为1
      7. 1.1.7. 第五问:
        1. 1.1.7.1. 此处考察的是js的运算符优先级问题。
        2. 1.1.7.2. 可以在这里看 运算符优先级 ,通过查上表可以得知点(.)的优先级高于new操作,于是就可以这样理解:new (Foo.getName)();所以实际上将getName函数作为了构造函数来执行,遂弹出2。
      8. 1.1.8. 第六问:
        1. 1.1.8.1. 第六问首先看运算符优先级括号高于new,实际执行为(new Foo()).getName()遂先执行Foo函数,Foo构造函数中没有为实例化对象添加任何属性,遂到当前对象的原型对象(prototype)中寻找getName,最终输出3
      9. 1.1.9. 第七问
        1. 1.1.9.1. 同样是运算符优先级问题。最终实际执行为:new ((new Foo()).getName)();先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new。遂最终结果为3
,