UDN-企业互联网技术人气社区
登录
注册
搜索
本版
文章
帖子
用户
搜索
本版
文章
帖子
用户
移动下载
试试手气
每日签到
首页
论坛
开发者大赛2019
U视野
U课堂
U专题
资源
沙龙
文库
开源文档
API服务
许可申请
赛事竞猜
云平台
iUAP平台
中台战略
用友开放平台
开发者大赛2019
大前端星学院
伙伴专区
企业互联网产品
小友RPA
产品那点事儿
资源
财务与共享服务
通用技术
HTML5|CSS3
JavaScript
数据库
Docker|云计算
J2EE技术
DevOps
开源
招聘面试
社区服务
论坛事务区
IT资讯
板块导航
UDN每周精选
HTML5
UAP工具下载
营改增
主数据平台
前端开发
用友研发员工必备
UDN 企业互联网技术社区
»
论坛
›
通用技术:JavaScript
›
说说牛客上的一道 JavaScript 题目
返回
发表新主题
浏览 :
849
回复 :
3
[面试]
说说牛客上的一道 JavaScript 题目
[复制链接]
cat77
发布主题
回复的帖子
10842
积分
威望
活力
U币
发消息
当前离线
楼主
发表于 2016-12-15 15:23:36
|
显示全部楼层
|
阅读模式
JavaScript
面试
牛客上有这么一道 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) ,但是碰到 null 、 0 、 false 就 GG 了,所以还是谨慎点吧。
问题到这里就可以比较完美地解答了。
bonus: instanceof 的问题
『 instanceof 会检查 this 的原型链上是否存在 foo.prototype 』,为什么说得这么拗口,是因为需要表达出 instanceof 本来就不是真的用来检测是否调用 new 的方法。
在题目里面,要求的是 a 需要从原型链上读取到特定的属性值,所以 instanceof 的作用刚好在这里能符合要求而已。
函数调用除了题目中的方法还有第三种方法,那就是 foo.call 、 foo.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 绑定的值是从 foo 上 new 出来的,换句话说,其原型链上存在 foo.prototype ,于是就骗过了 instanceof 。
于是 ES2015 来搭救你了,新增了一个 new.target 。于是修改成:
if (new.target !== undefined) {
// new 调用
if (name !== undefined) {
this.name = name
}
} else {
// 非 new 调用
return {
name: name
}
}
复制代码
相关帖子
•
如何利用PHP Cake框架构建应用
•
加快JavaScript加载和执行效率
•
JavaScript字符集编码与解码
•
理解关键渲染路径
•
ASP一句话也可以奇葩
•
WebView与JavaScript交互及JS的注入
•
JavaScript常用积累
•
JS —— 轮播图中的缓动函数的封装
•
GC与JS内存泄露
•
JavaScript For 循环的函数式改造
使用道具
举报
回复
提升卡
置顶卡
变色卡
地狱异类
发布主题
回复的帖子
151
积分
威望
活力
U币
发消息
当前离线
发表于 2016-12-19 11:12:18
|
显示全部楼层
js框架越来越火了, 不过本人还是喜欢原生的好, 自己写类库, 自己来封装,用着方便。。。。
使用道具
举报
回复
弑杀天下
发布主题
回复的帖子
131
积分
威望
活力
U币
发消息
当前离线
发表于 2016-12-19 11:12:18
|
显示全部楼层
回帖支持下楼主,请眼熟我,我叫“弑杀天下“
使用道具
举报
回复
帝王江山
发布主题
回复的帖子
132
积分
威望
活力
U币
发消息
当前离线
发表于 2016-12-19 11:12:22
|
显示全部楼层
Very Good!
使用道具
举报
回复
返回
发表新主题
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
用微信扫一扫
互动赢积分
关于我们
网站简介
友链交换
免责声明
联系我们
电话:010-86393388
邮件:
udn@yonyou.com
地址:北京市海淀区北清路68号
移动客户端下载
安卓客户端
苹果客户端
关注我们
微信公众号:yonyouudn
扫描右侧二维码关注我们
专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041
京ICP备05007539号-11
京公网网备安1101080209224
Powered by Discuz!
快速回复
返回列表
返回顶部