摘要:关于的指向问题算的上是中的一个十分重要的问题了。首先,的指向问题可以用一句话总结就是总是指向调用的对象,也就是说指向谁与函数声明的位置没有关系,只与调用的位置有关。此外注意几种特殊情况,特别是中的箭头函数。
关于this的指向问题算的上是js中的一个十分重要的问题了。今天把这个问题总结下,加深下自己对this的理解。
首先,this的指向问题可以用一句话总结就是:this总是指向调用的对象,也就是说this指向谁与函数声明的位置没有关系,只与调用的位置有关。这是判断this的一个大体原则,而具体的小原则按照优先级的不同大致可以分为以下几点:
new方式是优先级最高的一种调用方式,也就是说只要是出现new方式来调用一个函数,this肯定会指向new调用函数新创建的对象。
function() thisTo(a){ this.a=a; } var data=new thisTo(2); //在这里进行了new绑定 console.log(data.a); //22.显式绑定
显示绑定指的是通过call()和apply()方法对函数进行的调用,对this影响的优先级仅次于new绑定。
function thisTo(){ console.log(this.a); } var data={ a:2 }; thisTo.call(data)); //23.隐式绑定
隐式绑定是指通过对象的属性进行添加,从而调用this所在函数,该方式的优先级在显示绑定之后。
function thisTo(){ console.log(this.a); } var data={ a:2, foo:thisTo //通过属性引用this所在函数 }; data.foo(); //24.默认绑定
默认绑定是指当上面这三条绑定规则都不符合时采用的绑定规则,默认绑定会把this默认绑定到全局对象中,是优先级最低的绑定规则。
function thisTo(){ console.log(this.a); } var a=2; //a是全局对象的一个同名属性 thisTo(); //2二.this绑定的特殊情况 1.隐式丢失
当进行隐式绑定时,如果进行一次引用赋值或者传参操作,会造成this的丢失,从而最后将this绑定到全局对象中去。
1.1 引用赋值丢失
function thisTo(){ console.log(this.a); } var data={ a:2, foo:thisTo //通过属性引用this所在函数 }; var a=3;//全局属性 var newData=data.foo; //这里进行了一次引用赋值 newData(); // 3
原理:因为newData实际上引用的是foo函数本身,跟data对象没有任何关系,data对象只是一个中间桥梁。而newData就是一个本身不带a属性的对象,自然最后只能把a绑定到全局对象上了。
1.2传参丢失
function thisTo(){ console.log(this.a); } var data={ a:2, foo:thisTo //通过属性引用this所在函数 }; var a=3;//全局属性 setTimeout(data.foo,100);// 3
原理:setTimeout(fn,delay) { fn(); } 实际上fn是一个参数传递的引用(fn=data.foo),与引用丢失的原理一样
1.3 Function.prototype.bind()
为了解决隐式丢失的问题,ES5提供了bind方法,bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数。
function thisTo(){ console.log(this.a); } var data={ a:2 }; var a=3; var bar=thisTo.bind(data); console.log(bar()); //22.间接引用
间接引用是指一个定义对象的方法引用另一个对象存在的方法,这种情况下会使得this进行默认绑定。
function thisTo(){ console.log(this.a); } var data={ a:2, foo:thisTo }; var newData={ a:3 } var a=4; data.foo(); //2 (newData.foo=data.foo)() //4
原理:newData.foo=data.foo的返回值是目标函数的引用,因此调用的位置实际上是foo(),根据之前的隐式丢失里面说的原则,这里会应用默认绑定。
3.ES6箭头函数ES6的箭头函数在this这块是一个特殊的改进,箭头函数使用了词法作用域取代了传统的this机制,所以箭头函数无法使用上面所说的这些this优先级的原则,注意的是在箭头函数中,是根据外层父亲作用域来决定this的指向问题。
function thisTo(){ setTimeout(function(){ console.log(this.a); },100); } var obj={ a:2 } var a=3; thisTo.call(obj); //3
不用箭头函数,发生隐式丢失,最后的this默认绑定到全局作用域,输出3。
function thisTo(){ setTimeout(()=>{ console.log(this.a); },100); } var obj={ a:2 } var a=3;加粗文字 thisTo.call(obj); //2
用了箭头函数,不会发生隐式丢失,this绑定到外层父作用域thisTO(),thisTo的被调用者是obj对象,所以最后的this到obj对象中,输出2。
如果不用箭头函数实现相同的输出,可以采用下面这种方式:
function thisTo(){ var self=this; //在当前作用域中捕获this setTimeout(function(){ console.log(self.a); //传入self代替之前的this },100); } var obj={ a:2 } var a=3; thisTo.call(obj); //2三.总结:
this的绑定机制,就是要找到这个函数的直接调用位置,然后应用绑定的四条规则,当出现满足多个规则时,按照优先级的高低决定最终的绑定规则。此外注意几种特殊情况,特别是ES6中的箭头函数。
四.参考书籍:你不知道的JavaScript上卷
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82496.html
摘要:下面只探讨在浏览器中的指向,有兴趣的也可以把后面的例子在中跑一下。 我们知道js中有个全局对象就是window,如果在顶层声明一个变量如 var a=1 //就相当于window.a=1 同时有了node以后,js也可以在服务端运行了,官方解释为Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。通俗说node是一个支持js语法的容器,直接写js就可...
摘要:是什么这个单词是一个代词,所以应该是指代某些东西搞清楚的关键之处,就是要搞清楚指代了什么那么到底指代了什么呢就像你平时指着一个苹果说指着一个香蕉说同样,也会因为情况的不同而不同在中按照常规理解,的值是什么取决于函数如何被调用然而,的值是什么 1. this是什么 this这个单词是一个代词,所以this应该是 指代某些东西搞清楚this的关键之处,就是要搞清楚this指代了什么 那么t...
摘要:中指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下的指向。这就是我关于学习的总结,希望能给需要的人点帮助,然后有啥不足希望有大神能指点出来。 js中this指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下this的指向。 1.在对象中的this对象中的t...
摘要:中指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下的指向。这就是我关于学习的总结,希望能给需要的人点帮助,然后有啥不足希望有大神能指点出来。 js中this指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下this的指向。 1.在对象中的this对象中的t...
阅读 1264·2021-11-17 09:33
阅读 1727·2021-09-09 11:53
阅读 3178·2021-09-04 16:45
阅读 1356·2021-08-17 10:12
阅读 2362·2019-08-30 15:55
阅读 1768·2019-08-30 15:53
阅读 2396·2019-08-30 15:52
阅读 2547·2019-08-29 18:41