记录一道经典的面试题(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() 

二、分析

1、Foo.getName()------- 访问的是函数 Foo 上的静态属性,输出2

由于函数本身是对象,通过函数绑定属性和方法属于静态方法 ,可以直接调用。绑定在原型上的属性和方法要创建对象后才能调用,在构造函数对象内部定义的方法无法通过对象调用。

2、getName()--------结果输出为 4,而不是输出 5。这是因为JS 存在变量声明提升(所有声明的变量或声明的函数都会被提升到当前函数的顶部)。

3、Foo().getName()-------输出值为1, 先执行 Foo() 函数,定义全局变量 getName, 之后调用全局对象的 getName() 方法, 返回 1。
注意, Foo() 函数返回的 this 指向的是全局对象 window,所以调用的是全局对象 getName()。 函数里的 getName 绑定的是全局对象,通过 Foo 调用会报错。

4、getName() 调用全局函数, 因为执行 Foo(), 更新了 getName 的值,所以返回 1。

5、new Foo.getName() 考察了运算符的优先级。 . 的优先级高于 new, 相当于执行 new (Foo.getName)(), 相当于执行 getName 的构造函数,返回 2

6、new Foo().getName() 执行方式为 (new Foo()).getName() 先生成 Foo 对象, 再执行 getName() 函数。 在 new Foo() 返回的是新创建的空对象,由于对象这时还没绑定属性 getName, 所以这时调用的是原型上的 getName, 结果返回3

注意: 构造函数 return this,在执行 new 的时候,返回的是新创建的对象。

7、new new Foo().getName() 可以改写为 new ((new Foo()).getName)() 先初始化实例,然后将原型对象上的 getName() 作为构造函数执行,结果返回 3

将上面的代码进行优化就是

Foo.getName(); // 2
getName(); // 4
Foo();
getName(); // 1
getName(); // 1
Foo.getName(); // 2
(new Foo()).getName(); // 3
(new Foo()).getName(); // 3

可以参考更好的一篇博客https://www.cnblogs.com/xxcanghai/p/5189353.html述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值