资讯专栏INFORMATION COLUMN

说说牛客上的一道 JavaScript 题目

jk_v1 / 1822人阅读

摘要:原文牛客上有这么一道的题目。先来分析一下题目,和都从来,为什么同名的属性值不一样可以看出,是对这个函数的调用方式不一样,是函数的调用结果,而则是作为构造函数调用的结果。所以这题的重点应该是如何区分函数调用和构造函数调用。

原文:http://blog.e10t.net/talk-abo...

牛客上有这么一道 JavaScript 的题目。

//填写内容让下面代码支持a.name = “name1”; b.name = “name2”;
function obj(name){
    【1】
}
obj.【2】 = "name2";
var a = obj("name1");
var b = new obj;

【1】和【2】是填写的内容,【2】的答案是 prototype.name,没争议。

问题是【1】,参考答案居然是 if(name){ this.name = name;}return this;,这么随便地玩弄 this 不就是明摆着污染全局变量吗?暴力赋值不可取。

下面的一些高票讨论还说了一大堆解释的废话,连他自己都说自己好罗嗦。对,你不但罗嗦,而且还没有改错。注释里都说了给 window 的属性赋值,还不自知出问题,真是误人子弟。

先来分析一下题目,a 和 b 都从 obj 来,为什么同名的属性值不一样?可以看出,是对 obj 这个函数的调用方式不一样,a 是 obj 函数的调用结果,而 b 则是 obj 作为构造函数调用的结果。所以这题的重点应该是如何区分_函数调用_和_构造函数调用_。

一个关键字 new 决定了不同。new 的作用是什么呢?MDN 上说了,面试也会考你的,简单来说是三步,new foo

生成一个继承于 foo.prototype 的对象

foo 会被调用,其中的 this 值会被绑定为 1 中的对象

如果 foo 没有返回一个对象(注意是对象!),则返回 1 的对象

从 2 就可以看出 this 值会被 new 绑定为一个确定的对象,而不是像普通函数调用中那样自己不可预料,要看上下文的进程。

于是就可以在这里做文章。先来判断 this 的值。

if (this instanceof obj) {}

instanceof 会检查 this 的原型链上是否存在 foo.prototype。也就是说能判断是否满足第 1 条,确保了对象能从 prototype 中读取到 name 属性。(毕竟代码中并没有给 b 的赋值中传入)

instanceof 并不是完美的判断方法,但是在这里足够了,后面会谈到这个问题。

if (this instanceof obj) {
    // new 调用
} else {
    // 非 new 调用
    return {
        name: name
    }
}

非 new 调用的情况下,直接返回一个新对象就 OK 了。

而在 new 调用的情况下,可以看到 function obj(name) 定义的时候是有参数的,调用的时候却没参数,这就要小心了,为了安全起见,还是判断一下为妙。

if (this instanceof obj) {
    // new 调用
    if (name !== undefined) {
        this.name = name
    }
} else {
    // 非 new 调用
    return {
        name: name
    }
}

一般来说,判断会写成 if (name),但是碰到 null0false 就 GG 了,所以还是谨慎点吧。

问题到这里就可以比较完美地解答了。

bonus: instanceof 的问题

instanceof 会检查 this 的原型链上是否存在 foo.prototype』,为什么说得这么拗口,是因为需要表达出 instanceof 本来就不是真的用来检测是否调用 new 的方法。

在题目里面,要求的是 a 需要从原型链上读取到特定的属性值,所以 instanceof 的作用刚好在这里能符合要求而已。

函数调用除了题目中的方法还有第三种方法,那就是 foo.callfoo.apply,而且也能为函数指定 this 的值(所以还有 bind)。因此是存在方法调戏 instanceof 的。

foo.prototype.name = "foo"
var midman = new foo("fake foo")
var a = foo.call(midman)
var b = foo.call(midman, "b")
a  // undefined, WTF?!
b  // undefined, WTF?!

这里的 foo 调用的方式是作为函数来调用,但是为 this 绑定的值是从 foonew 出来的,换句话说,其原型链上存在 foo.prototype,于是就骗过了 instanceof

于是 ES2015 来搭救你了,新增了一个 new.target。于是修改成:

if (new.target !== undefined) {
    // new 调用
    if (name !== undefined) {
        this.name = name
    }
} else {
    // 非 new 调用
    return {
        name: name
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91344.html

相关文章

  • 我的秋招复盘——回顾2022秋招经历

    摘要:接下来,我主要从三个阶段回顾我的秋招,分别是前期中期尾声。到了这里,我的秋招算是正式的尘埃落定了,签完三方后,我的秋招结束了。四复盘总结这次的复盘主要是我自己整个秋招的历程缩影,很多细节无法在一篇文章就说清楚。 ...

    longshengwang 评论0 收藏0
  • 从简历被拒到收割今日头条 offer,我用一年时间破茧成蝶!

    摘要:正如我标题所说,简历被拒。看了我简历之后说头条竞争激烈,我背景不够,点到为止。。三准备面试其实从三月份投递简历开始准备面试到四月份收,也不过个月的时间,但这都是建立在我过去一年的积累啊。 本文是 无精疯 同学投稿的面试经历 关注微信公众号:进击的java程序员K,即可获取最新BAT面试资料一份 在此感谢 无精疯 同学的分享 目录: 印象中的头条 面试背景 准备面试 ...

    tracymac7 评论0 收藏0
  • 从简历被拒到收割今日头条 offer,我用一年时间破茧成蝶!

    摘要:正如我标题所说,简历被拒。看了我简历之后说头条竞争激烈,我背景不够,点到为止。。三准备面试其实从三月份投递简历开始准备面试到四月份收,也不过个月的时间,但这都是建立在我过去一年的积累啊。 本文是 无精疯 同学投稿的面试经历 关注微信公众号:进击的java程序员K,即可获取最新BAT面试资料一份 在此感谢 无精疯 同学的分享目录:印象中的头条面试背景准备面试头条一面(Java+项目)头条...

    wdzgege 评论0 收藏0
  • 牛课网编程~~倒置字符串

    摘要:倒置字符串前言解法思路解析解法完整代码解法思路解析解法完整代码最后的总结前言一道牛客网的编程题。。。倘若我们要倒置的字符串很长,新开辟空间会耗费资源的。 倒置字符...

    不知名网友 评论0 收藏0
  • 一道前端面试题引发的思考

    摘要:直接开始题目是厉害了说句实话开发中谁写成这样保证会被打死。不过面试就是面试,有面试官的考量点。官方是这么说的。结果完美,不过小姐姐的意思是数组的方法会自动触发数组的。 直接开始题目是 if(a==1 && a==2 && a==3){ alert(厉害了) } 说句实话开发中谁写成这样保证会被打死。 不过面试就是面试,有面试官的考量点。 我理解的点有两个 1、隐式类型转换 先说...

    gaomysion 评论0 收藏0

发表评论

0条评论

jk_v1

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<