函数经典面试题

方式1:一个构造函数,里面有个全局变量getName 指向一个匿名函数

function Foo(){
    getName = function (){
    console.log(1);
    }
  return this;
}

方式2:构造函数的一个属性getName 指向一个匿名函数
Foo.getName = function(){
  console.log(2);
}

方式3:构造函数的原型上有个getName方法
Foo.prototype.getName = function (){
  console.log(3);
}

方式4:定义一个变量指向一个匿名函数
var getName = function (){
  console.log(4);
}

方式5:声明一个叫getName的函数
function getName(){
  console.log(5);
}

 

//请写出下面输出的结果

Foo.getName();        //2

getName();          //4

Foo().getName();        //1

getName();            //1

new Foo.getName();        //2

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

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

接下来废话不多说,分析每个执行结果:

----->1. Foo.getName()

  此句为函数Foo的静态方法,输出结果为2.

----->2. getName()

   单独看此句首先想到的是一般会有个全局声明的函数方法,方式5"function getName(){}",但要放在这个上下文环境中,那肯定不一样了,因为还有个方式4"var getName = function(){}",这里要考察一个知识点,当定义的变量和声明的函数重名了怎么办?答:它们都会预解析,函数声明提前于变量声明,但是最终会被后者变量覆盖,so输出结果为4.

----->3. Foo().getName()

  此句有个执行顺序的,先执行方式1的Foo(),其相当于window.Foo(),故此this指向window,另外Foo()函数的第一句是getName = function(){}是一句函数赋值语句,注意它没有var声明,是一个全局变量,如果先执行window.getName()结果是4,如果先执行Foo()会返回一个window,那此时函数经典面试题_第1张图片

此时方式4已经被覆盖了,所以下面再执行全局getName()就都是结果为1了。

----->4. getName()

  此处跟执行的Foo().getName()有关,因为这个变量已经被Foo函数执行时修改了,所以结果为1

----->5. new Foo. getName()

  此句首先还是看下运算符的优先级吧,结果大概就是(new Foo()> Foo() > new Foo)相当于new (Foo.getName)();

先运算方式函数调用Foo.getName(),静态调用,回到方式1的执行语句了,结果为2,再new一个Foo实例对象,实际上将getName函数作为了构造函数来执行,结果为2

----->6. new Foo(). getName()

  此句先看运算符相当于(new Foo()).getName(),先指向Foo函数,而此时Foo作为构造函数却有返回值,所以这里需要说明下js中的构造函数返回值问题

构造函数返回值

 在传统语言中,构造函数不应该有返回值,实际执行的返回值就是此构造函数的实例化对象。

而在js中构造函数可以有返回值也可以没有

1.没有返回值则按照其他语言一样返回实例化对象

函数经典面试题_第2张图片

2.若有返回值则检查其返回值是否为引用类型,如果是非引用类型,如基本类型(string,number,boolean,null,undefined)则与无返回值相同,实际返回其实例化对象

函数经典面试题_第3张图片

3.若返回值是引用类型,则实际返回值为这个引用类型

函数经典面试题_第4张图片

原题中返回的是this,而this在构造函数中本来就代表当前实例化对象,所以Foo函数返回实例化对象。

之后调用实例化对象的getName函数,因为在Foo()构造函数中没有为实例化对象添加任何属性,所以到当前对象的原型对象(prototype)中寻找getName,所以找到了,结果为3.

----->7. new new Foo(). getName()

  同样先运用优先级问题,实际相当于new ((new Foo()).getName)();

先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次被new,结果为3

 

转载于:https://www.cnblogs.com/itsmart/p/11322228.html

你可能感兴趣的:(函数经典面试题)