js奇葩写法解说
来源:互联网 发布:js 删除一个数组元素 编辑:程序博客网 时间:2024/05/16 10:45
问题
var a=1;var b={ a:2, b:function(){ console.log(this.a); }(), f:this.f=function(){ console.log(this.a); }};function f(){ console.log(3); }f();b.f();(b.f)();(0,b.f)();
有这样一段代码,答案是1、1、2、2、1,第一个答案是1是因为b.b是个立即执行函数,但是为什么后面的答案是1221了??
回答
首先我觉得这是一道人为构造的“戏过了的”JS题目,涉及到函数声明提升、this指向、函数表达式、逗号表达式,但是日常谁写出这样类似的代码肯定是活不久了的,下面尝试分解一下:
首先有一个知识点是声明提升,这里有一个全局作用域下的f()
函数,这个会被提升到顶端,所以你原来的代码实际上执行起来是这样的顺序:
//这个函数声明提升啦function f(){ console.log(3); }var a=1;var b={ a:2, b:function(){ console.log(this.a); }(), f:this.f=function(){ console.log(this.a); }};//function f(){ console.log(3); }f();b.f();(b.f)();(0,b.f)();
而在对象b中的属性f中,是一个函数表达式,b.f:this.f=function(){...}
相当于b.f=this.f=function(){...}
,这个赋值是立即发生的,只是函数体内不立即执行,所以也就是说,b.f和this.f都指向了这个匿名函数,而这个this是window,变成了b.f=window.f=function(){...}
,于是这个window.f
覆盖了由于声明提升到顶的那个f(那个f也是在window下的),明白了这个再看:
第一个“1”,题目理解没错,是因为b.b是个立即执行的函数,输出的
第二个“1”,是f()的输出,也就是window.f(),这个根据上面的分析,看到由于声明提升和对象内覆盖赋值,这个执行的是
console.log(this.a);
函数体,this指向window,所以是1;第三个“2”,是b.f()的输出,因为b.f也是指向了那个函数体,但此时this指向调用这个函数的对象b,所以是输出2;
第四个“2”,无非是上面的那个变成了函数表达式,b.f还是对原来函数的引用,this的值得到维持,没啥,还是一样的;
第五个“1”,在执行函数之前括号里是一个逗号表达式,我们知道逗号表达式,是取最后一项的值作为整个表达式的值,但是这个时候,this的值不能得到维持,因为这个逗号表达式相当于把原来的函数体赋值给了整个表达式做表达式的值,这时候的this就变成了window,所以输出1
为了说明这个坑爹的结果,尤其是第5个值的输出,我去翻了《JS高程》:
转载:https://segmentfault.com/q/1010000008632480/a-1020000008633432
- js奇葩写法解说
- js 各种奇葩写法
- js 各种奇葩写法2
- JS中各种奇葩的匿名函数写法
- Freescale WINCE 代码奇葩写法
- 奇葩的JS编码
- 奇葩的JS数组
- js offsetHeight offsetWidth 解说
- js offsetHeight offsetWidth 解说
- js offsetHeight offsetWidth 解说
- js事件列表解说
- js offsetHeight offsetWidth 解说
- swfobject.js 详细解说
- PDF.js 详情解说
- Js写法
- 记一次奇葩的Js劫持事件
- 奇葩的JS-隐式转换
- Js事件触发列表与解说
- Linux 下根据进程名来杀死进程
- LK ARM64 asm.S处理
- c# 的正则运算[小窍门]
- iOS------消息、Category和protocol
- Linux系统安全之ssh后门
- js奇葩写法解说
- Map.EntrySet的用法
- 如何在一个没有导航栏的控制器视图里面用模态视图弹出别的控制器视图
- 特征工程简介
- APP support
- linux sar命令详解
- 打印倒三角
- SAP OnLine Help(系统帮助)
- win7双击jar包没反应(已解决)