问答

一道前端面试题

作者:admin 2021-09-23 我要评论

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

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)
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); }

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

代码如上,都可以复制到F12执行看下,等大佬作答,实在懵逼### 题目描述

###

把你上面的代码分为两部分:

  • 代码部分
  • 问题部分

先看代码部分

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); }

基于以下原因:

  • 函数提升变量提升
  • 函数提升优先级高于变量提升
  • 函数提升不会被变量提升的声明覆盖

改造上面的代码:

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

function getName(){ console.log(5); } // 注意这里

var getName; // 这里

Foo.getName = function() { console.log(2); };
Foo.prototype.getName = function(){ console.log(3); };

getName = function() { console.log(4); };  // 这里

然后再看问题部分

  1. Foo.getName()
    这个没有什么好说的,执行下面的代码:

    Foo.getName = function() { console.log(2); };

    所以输出2

  2. getName()
    这个再看上面的代码,getName被赋值为function() { console.log(4); };
    所以输出4
  3. Foo().getName()
    这个分两部分:Foo().getName():

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

    执行这个代码之后,getName被重新赋值为function(){ console.log(1); },然后返回this
    这个this指的是谁?Foo()函数调用,没有使用new,所以这个this指的是全局this
    所以现在这个代码变成了全局的getName()的调用,就是赋值的那个getName的函数的调用。
    所以输出1

  4. getName()
    这个现在跟【3】中的getName是一样的。
    所以输出1
  5. new Foo.getName()
    这个写法比较迷惑人,转换一下,就是new (Foo.getName)(),什么意思呢,就是相当于:

    var a = Foo.getName;
    new a();

    这样写是不是清楚一些,所以答案就清楚了。
    输出2

  6. new Foo().getName()
    这个比较简单,简单拆分一下吧:

    var obj = new Foo();
    obj.getName();

    obj原型链上存在一个getName函数,Foo.prototype.getName = function(){ console.log(3); };
    所以输出3

所以答案就是:2 4 1 1 2 3

###

参考链接:https://juejin.im/post/5d8d82...

Foo.getName(); // 2,调用 Foo.getName 函数

getName(); // 4
// 原因
// var getName = function() { console.log(4); };
// function getName(){ console.log(5); }
// 这两句都声明 getName 函数,因为变量提升原则,变成了下面的执行顺序:
// var getName;
// function getName(){ console.log(5); }
// getName = function() { console.log(4); } 所以最后执行结果为4

Foo().getName(); //1
// 先执行 Foo(),?? Foo 函数里的 getName 函数前面没有 var/let,所以是个全局变量
// 重写了全局函数 getName,Foo返回的结果是 this,
// 根据默认绑定原则,this 代表全局作用域

getName(); // 1,调用的也是全局函数 getName()

new Foo.getName(); //2
// 等效于 new (Foo.getName()),执行 Foo.getName()

new Foo().getName(); //3
// 等效于 (new Foo()).getName(),先执行 Foo(),得到 this
// 此时 this 是新建的对象,此对象上没有 getName 方法,就去原型链上找

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 一道前端面试题

    一道前端面试题

  • angular如何定义全局变量,在所有控制

    angular如何定义全局变量,在所有控制

  • js被选项命名check和choose和select用

    js被选项命名check和choose和select用

  • umi@3.x  dva 数据如何本地缓存读取

    umi@3.x dva 数据如何本地缓存读取

腾讯云代理商
海外云服务器