关于JS的两道有意思题--关于this的绑定

来源:互联网 发布:python tcp连接不释放 编辑:程序博客网 时间:2024/06/07 05:23

  --昨天刚差不多学完vue,想重构个CNode中文社区(这好像是每个学完Vue都准备练手的项目),可是一点头绪没有啊!逛了几个大佬的教程,还是没有得到我想要的。那时候图书馆也快关门了,就想着今天有空写写。今天早上又去答辩了课程设计-B树,老师不按常理问问题搞得我也挺烦的。说回那个CNode,自己技术栈还是差了点,有空补补技术栈再写一篇小白版CNode重构教程吧。

  开心的是,今天逛论坛看到一个老哥一年前发的两道题,感觉挺有意思的。主要涉及的也是作用域和this的语法。正好我之前也读过《你不知道的javas》上卷(好书啊!!!),强烈推荐这一系列书,在你学完JS迷茫期的时候读读这系列书,你会发现很多JS有意思的东西。学习就是这样,学的越多感觉自己懂得越少。下面分享下那两道题,顺便用我比较浅显的语言分析一下。

  第一题:关于this绑定的问题。

var length = 10;function fn() {    console.log(this.length)};var obj = {    length: 5,     method: function (fn) {        fn();        arguments[0]();        fn.call(obj, 14);    }};obj.method(fn, 1);//10,2,5
  先来一些知识铺垫:

  this的绑定机制:

   简单来说就是this的绑定是在运行时绑定的,他取决于函数的调用方式。函数调用的时候会有一个记录,这个记录里面就存有this属性。简单来说,就是一般this指向什么,取决于函数在哪里被调用的!

  this的三种绑定形式:

1.默认绑定

  当this运用了默认绑定的时候,此时this就指向全局对象。你也可以这么理解,函数是在全局作用域被调用,理所应当的指向全局对象。

2.隐式绑定

  当函数调用拥有上下文对象的时候,通俗的讲就是是否被某个对象拥有。

  看下面这个例子

function foo(){console.log( this.a );}var a=2;var obj = {a:1,foo:foo};obj.foo();//1foo();//2
这里,foo被obj内部的foo属性引用,obj.foo()可以这么理解,调用obj内的foo,这时的foo调用被obj拥有,所以this当然指向obj。我用的Foo函数都是我的属性,this不应该指向我吗?

3.显式绑定

  显式绑定就比较容易发现,一般来说有:call,apply绑定;bind绑定;函数调用时一个类似bind绑定的参数绑定;new绑定

  优先级:new > 显式 > 隐式 >默认。

接着看上面的题。

大致就是,定义了一个全局的length为10,一个函数声明fn输出this.length,一个对象包含一个length为5,有一个方法返回fn(),arguements[0](),fn.call(obj,14);最后调用这个方法,问我们输出的是什么。

分析:

第一步:obj.method(fn,1),就是调用obj的method,然后传入参数fn,1。此时的arguments为{‘0’:fn,'1':1}

第二步:fn()这就是在全局作用域调用fn(),虽然他在method中,但是这只是在method下调用了fn(),所以this指向全局对象,第一个输出10

第三步:arguements[0](),arguments[0] = fn,所以就是调用arguements中的fn,此时fn的this就隐式绑定到了argums,这个等价于fn.call(arguments)。那么为什么会输出2呢?MDN上对arguments的描述:The arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length. 懂了吧?这里输出的就相当于arguments.length,两个参数当然就是2了。

第四步:fn.call(obj, 12)简单了啊,显式绑定啊,this绑定到obj,输出5!

this绑定机制那么复杂,那么容易让人误解,所以ES6出了胖箭头,就把this定义在词法作用域。简单改写一下上面的函数

var length = 10;fn = ()=>{console.log(this.length)}var obj = {    length: 5,     method: function (fn) {        fn();        arguments[0]();        fn.call(arguments);        fn.call(obj, 14);    }};obj.method(fn, 1);//10,10,10
胖箭头=>把this绑定到了fn,fn是什么它就是什么,这里fn是个全局对象,所以this也指向全局对象。有点像任他风吹雨打 我自岿然不动的感觉。

原创粉丝点击