一道函数题考察基本功

题目:代码如下,求输出结果

function Foo() {
    getName = function () {
        console.log(1);
    }
    return this;
}
Foo.getName = function () {
    console.log(2);
}
Foo.prototype.getName = function () {
    console.log(3);
}
var getName = function () {
    console.log(4);
}
function getName() {
    console.log(5);
}

1,函数和变量提升

题目:

Foo.getName();  // 2
getName();      // 4

Foo.getName()分析:
Foo是一个函数,而函数其实也是一个对象,可以给函数赋值。
Foo.getName();会执行Foo.getName函数体内的处理,所以显示结果为2。

getName()分析:
getName存在变量提升,我们来看看变量提升后的样子就知道为什么getName();的结果是4了。

//这里是提升之后的内容
var getName;
function getName() {
    console.log(5);
}
////////////////////
function Foo() {
    getName = function () {
        console.log(1);
    }
    return this;
}
Foo.getName = function () {
    console.log(2);
}
Foo.prototype.getName = function () {
    console.log(3);
}
getName = function () {
    console.log(4);
}

可以看到,var getName = function ()的定义var getName被提升到最前面了,赋值还保留在原来的位置。而function getName()...本身就是定义,所有整个被提升到前面了。
所以,根据最终的赋值结果来看,显示结果是4。

2,函数和作用域

题目:

Foo().getName();  // 1
getName();  // 1

Foo().getName()分析:

  1. Foo的函数体内,getName是没有用var声明的,所以getName是一个全局变量。
  2. Foo()的意思是运行Foo的函数体,这个函数体中做的事情就是,把全局变量getName的函数体替换成console.log(1)
  3. Foo函数体的返回值是this,这里的this指向的是window对象。Foo().getName();就相当于window.getName();,也就是直接调用getName()函数,显示结果就是1。

getName()分析:
在这里,getName()this.getName()window.getName()这三者的意思是一样的。所以显示结果也是1。

3,运算符和优先级

MDN运算符优先级

从以上的MDN运算符优先级资料中可以看出,"."运算符的优先级是比"new"运算符的优先级高的。

题目1:

new Foo.getName();  // 2

分析1:

  1. 相当于new (Foo.getName)();
  2. 执行Foo.getName函数,这时候就已经输出2了
  3. 实例化一个对象

题目2:

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

分析2:

  1. 相当于(new Foo()).getName();
    .运算符的优先级是19,就是指.会优于其他运算符之前执行,但是执行点的时候,是按照点前和点后的表达式依次执行的,因为Foo后面有个括号,所以new运算符是归Foo()这个函数的。
  2. 执行new Foo(),实例化一个对象,这个对象中拥有Foo.prototype.getName方法。
  3. 执行.getName(),调用Foo.prototype.getName方法,输出为3。

题目3:

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

分析3:

  1. 相当于new (new Foo()).getName();
    .运算符的优先级是19,就是指.会优于其他运算符之前执行。执行点的时候,是按照点前和点后的表达式依次执行的。
    看看左边的new new Foo(),带参数的new优先级是比不带参数的new优先级高的,所以左边的部分就相当于new (new Foo())
    什么是带参数的new:new Foo()
    什么是不带菜蔬的new:new Foo

  2. 执行(new Foo()).getName(),相当于foo.getName()
    foonew Foo()出来后的实例,这个结果和题目2是一样的。这时候已经输出3了。

  3. 执行new,实例化一个对象

你可能感兴趣的:(一道函数题考察基本功)