JS经典题

题目如下:

1,function fn(){
    getName = function(){alert('大木')};
    return this;
}

2,fn.getName = function(){ alert('大木2')}

3,fn.prototype.getName = function(){ alert('大木3')}

4,var getName = function(){ alert('大木4')}

5,function getName(){ alert('大木5')}

请输入如下结果

  1. fn.getName();
  2. getName();
  3. fn().getName()
  4. getName()
  5. new fn.getName()
  6. new fn().getName()
  7. new new fn().getName()

-

-

-

-

-

-

-

-

-

-

答案

  1. fn.getName(); ———- 大木2

  2. getName(); ————- 大木4

  3. fn().getName() ———- 大木

  4. getName() ————— 大木

  5. new fn.getName()——–大木2

  6. new fn().getName()—— 大木3

  7. new new fn().getName()–大木3

解析

  1. 该题首先定义了一个构造函数fn,fn内部定义了一个全局变量 getName 然后返回 this
  2. 给fn定义了一个静态属性getName,注意次属性只能由 fn函数自己调用
  3. 给构造函数fn原型链添加一个getName方法
  4. var 定义一个变量 getName
  5. 定义一个普通函数getName

JS变量解析方式是先将变量申明和函数申明放到作用域最顶部,函数和变量同名会用函数申明覆盖变量申明,然后再进行赋值操作,所以解析后代码如下

var getName; //无效,被覆盖

function getName(){ alert(‘大木5’)} //覆盖上面的变量申明

function fn(){
getName = function(){
alert(‘大木’ );
return tis;
}

fn.getName = function(){ alert(‘木2’)}

fn.prototype.getName = function(){ alert(‘木3’)}

getName = function(){ alert(‘大木4’)} //普通函数被重新指向一个新函数

第一问 fn.getName(); 是执行函数的静态变量  ---大木2
第二问 getName() 执行普通函数 ---大木4
第三问 fn().getName() ==先执行fn(),将全局变量getName指向新函数 alert('大木')
      返回this-->指向window,再执行window.getName()  --大木
第四问 getName() 直接执行被在fn内部改变指向后的getName --大木
第五问 new fn.getName() 是JS运算符优先级.语法高于new,所以是先执行(fn.getName)(),
      然后将执行后的函数实例化操作 --大木2
第六文 new fn().getName()--new 带参数(即 new Foo())和函数自调用(即先 Foo()),
      而 new 带参数的优先级是高于函数调用的! 所以此处执行顺序为(new fn()).getName()
      即fn数理化后执行原型链方法getName --大木3
第七问 同理先执行new fn()返回实例化对象A,new A.getName()同第五问==new(A.getName)()--大木3

注意点:

1,变量提升,同名函数申明会覆盖变量申明
2,“.”语法操作优先级高于 new语法操作
3,函数自调用 fn() 优先级 小于 new fn()

OVER