摘要:例如通过,调用时强制把它的绑定到上。箭头函数问题箭头函数体内的对象就是定义时所在的对象,而不是使用时所在的对象,固定不变。
刚入门javascript,关于this的学习,花了自己挺多的时间,做了比较多的功课,看了一篇又一篇的文章,也看了一些书籍,今天就结合看的那些东西总结下自己所学到的东西,方便留着以后回看,进一步的学习,这篇文章会不断的更新,不断的更新自己的想法,现在还是一个入门不久的小白,若有错误,恳请指出!
this这个关键字在整个javascript中用处挺广泛的,例如,在闭包,对象等中都会用到,掌握好this个人认为是学好javascript的关键之一了,当然其中还有:闭包、原型、原型链、对象等理论基础也是几个关键点,都得用心的学习。
函数中的调用
javascript函数中this的指向不是在函数定义的时候确定的,而是在函数调用时确定的,用我自己的话来说:就是看这个函数是在什么环境下被调用的,如果在全局环境下调用这个函数,那么这个函数中的this就指向了window,看下面的这个例子:
var a = 2; function foo() { console.log(this.a);//2 } foo();
函数foo()的调用是在全局环境下调用的,即这个函数中的this指向的就是window(其实这也可以叫函数的默认绑定,在后面我会介绍),函数控制台输出的就是window.a,函数内部即使没有定义变量,同样也是可以输出a的值,这其中也涉及到了作用域链的相关知识点,由内向外搜索,这里就不解释了,这个可以自己去了解。
加大一点难度,看看这个例子,可能会让你开始有点迷惑,我自己在不是很理解this在函数中的调用,是很迷惑的,不懂,相关知识点一遍一遍的反复的看,大家来看看,是上面的例子的改版:
var a = 2; function foo() { var a = 3; console.log(this.a);//2 } foo();
这个函数foo()的输出值,大家应该会感到很意外,我去,a怎么会输出的是2,不应该是3的吗,是不是有问题啊,哈哈哈哈哈,起初我是觉得是有问题的,函数中明明也声明了一个变量a,输出的值肯定是3啊,想了一些时间没有想明白。回过头来看看this是怎么说的,就清楚了为什么a输出的值依旧是2了:javascript函数中this的指向不是在函数定义的时候确定的,而是在函数调用时确定的。认真的解读下这句话就很清楚的知道变量a输出的值肯定就是2了,this的指向只与普通函数的调用有关,箭头函数另外再说,这个foo()函数的调用时在全局环境,因此this是指向全局对象,即window,所以输出a的值依旧还是2了,而不是想当然的认为是3了,这下应该比较清楚了吧。大家再看下下面的这个例子:
var a = 2; function foo() { a = 3; console.log(this.a); } foo();
这个foo()函数输出的又是什么值呢,这个就是大家认为的3了,这就不解释了,看了上面的应该就比较清楚了。
绑定规则
默认绑定
函数独立调用,直接使用不带任何修饰的函数引用进行调用,其this默认指向window对象,第一部分的第一个例子就是默认绑定,这就不在记述。
隐式绑定
函数调用时拥有一个上下文对象,就好像这个函数是属于这个对象的一样。例如:
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; obj.foo();//2
当函数foo()被调用时,其引用有obj这个对象,即函数调用中的this绑定到了这个对象,this.a就相当于obj.a,输出的值就为2。
隐式绑定丢失
被隐式绑定的函数丢失绑定对象,其会应用默认绑定,这也是this应用中容易出错的地方,关键还是对this调用位置没有理解清楚。例如:
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; var bar = obj.foo; var a = "全局"; bar();// "全局"
其实很好理解为什么this指向的全局对象window,关键还是看函数的调用位置,虽然函数foo()被当作引用添加到obj对象中,它也仅仅是一个引用,变量bar也就是obj.foo的一个引用的传递,然而bar()是独立调用的,不带任何修饰的函数调用,所以函数调用中的this是绑定到了全局对象,即this.a是window.a,输出的值为"全局"。
显式绑定
显式绑定多数是用call()、apply()函数,他们的第一个参数是一个对象,是给this准备的,函数调用时将其绑定到this,也就是直接指定this的绑定对象。例如:
function foo(){ console.log(this.a); } var obj = { a:2 }; foo.call(obj);//2
通过call(),调用foo时强制把它的this绑定到obj上。
apply()的使用和call()一样,它们不同的在于传参的方式不一样,call()接受的是若干个参数的列表,apply()接受的是一个包含多个参数的数组,具体作用可以自己去了解。
new绑定
如果是一个构造函数,用new来调用,那么绑定的将是新创建的对象。例如:
function foo(a){ this.a = a; } var bar = new foo(2); console.log(bar.a);//2
使用new来调用foo()时,构造一个新的对象并把它绑定到函数调用中的this上面,即this.a就是bar.a,输出的值为2。
箭头函数this问题
箭头函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象,固定不变。例如:
function foo(){ setTimeout(()=>{ console.log(this.a); },100); } var obj = { a:2 } foo.call(obj);//2 function foo(){ setTimeout(function(){ console.log(this.a); },100); } var obj = { a:2 } foo.call(obj);//undefined
看上面的两个例子,第一个使用的是箭头函数,第二个使用的是普通函数,最后的结果不一样的,输出一个是2,一个是undefined。原因很简单,箭头函数中this对象是在定义所在的的对象,普通函数中的this对象的指向是可变的。
本例第一个用例中箭头函数中的this总是指向函数定义生效时所在的对象,即为obj,所以箭头函数的this.a就是obj.a,输出的值就为2。第二个用例中,根据调用的位置,普通函数this的指向是可变的,这个用例中this的最终指向的是全局对象window,即this.a就是window.a,全局环境中没有定义变量啊,所以输出的值为undefined。为什么第二个用例的this指向的是全局对象,有一种解释是:对象中的方法的函数被当作函数模式所触发,所以它的this是指向window的,这也是this应用容易出错的一个地方。如果也想让它的this指向定义时绑定的对象,做如下改变就行了:
function foo(){ var that = this; setTimeout(function(){ console.log(that.a); },100); } var obj = { a:2 } foo.call(obj);//2
将this临时传递给一个变量that,通过that使用,这样输出的值就为2了。
结束
1.this的掌握的关键在于它的调用位置,这个理解清楚了就不太容易出错。
2.要区分好普通函数和箭头函数中this的使用,不要搞混淆了。
3.学好这些理论基础是学好javascript的基石,对以后理解和写javascript的逻辑提供很好的帮助
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/89652.html
摘要:总结本博文通过介绍执行上下文和作用域的异同的使用以及变量对象,让我们加深对语言特性的理解。首先,我们介绍了执行上下文和的的关系,并且执行上下文是具有对象的然后,介绍了作用域使变量在作用域范围内可见,并且作用域是基于函数的。 接上一篇Javascript Context和Scope的学习总结01【转自cnblogs的JKhuang】(可能是segmentfault对单篇文章发布字数有限制...
摘要:全局环境在全局环境中使用,它会指向全局对象。作为构造函数调用中的构造函数很特殊,如果不使用调用,则和普通函数一样。作为又一项约定俗成的准则,构造函数以大写字母开头,提醒调用者使用正确的方式调用。 在JavaScript中,this关键字是动态绑定的,或称为运行期绑定,这极大地增强的我们程序的灵活性,同时也给初学者带来了很多困惑。本文总结了this的几个使用场景和常见误区。 全局环境 在...
摘要:发生这种情况的条件是当引用类型值的对象恰好为活跃对象。总结本文介绍中的使用,更重要的是帮助我们能更好地理解值在全局函数构造函数以及一些特例的情况中值的变化。然而,由于对于来说没有任何意义,因此会隐式转换为全局对象。 接上一篇Javascript this 的一些学习总结02【转自cnblogs的JKhuang】 引用类型以及this的null值 对于前面提及的情形,还有例外的情况,当调...
摘要:布尔值表示捕获阶段调用事件处理程序,表示冒泡阶段通过对象的方法,也可以定义事件的回调函数。对象会被作为第一个参数传递给事件监听的回调函数。布尔默认值是,当设置成时用以取消事件的默认行为与中的相同。 其实这篇文章挺早之前就写了,但是由于sf保存方面的bug,所以当时写了一大堆,结果没保存,觉得这个没写完是个不小的遗憾,今天正好有空,就给补充下了,也正好给我的javascript学习总结做...
摘要:正文执行环境也称为环境是中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。简而言之,执行环境是基于对象的,而作用域是基于函数的。 前述 在我们学习Javascript过程中,常常会遇到作用域(Scope)和执行上下文(Context)等概念。其中,执行上下文与this关键字的关系密切。 有面向对象编程经验的各位,对于this关键字再熟悉不过了,因此...
阅读 1876·2021-11-19 09:40
阅读 2593·2021-08-30 09:46
阅读 2177·2021-08-03 14:01
阅读 2648·2019-08-30 10:54
阅读 1196·2019-08-29 16:38
阅读 1439·2019-08-29 11:02
阅读 2536·2019-08-28 18:16
阅读 1679·2019-08-28 18:09