刚入门javascript,关于this的学习,花了本身挺多的时间,作了比较多的功课,看了一篇又一篇的文章,也看了一些书籍,今天就结合看的那些东西总结下本身所学到的东西,方便留着之后回看,进一步的学习,这篇文章会不断的更新,不断的更新本身的想法,如今仍是一个入门不久的小白,如有错误,恳请指出!javascript
this这个关键字在整个javascript中用处挺普遍的,例如,在闭包,对象等中都会用到,掌握好this我的认为是学好javascript的关键之一了,固然其中还有:闭包、原型、原型链、对象等理论基础也是几个关键点,都得用心的学习。java
函数中的调用数组
javascript函数中this的指向不是在函数定义的时候肯定的,而是在函数调用时肯定的,用我本身的话来讲:就是看这个函数是在什么环境下被调用的,若是在全局环境下调用这个函数,那么这个函数中的this就指向了window,看下面的这个例子:闭包
var a = 2; function foo() { console.log(this.a);//2 } foo();
函数foo()的调用是在全局环境下调用的,即这个函数中的this指向的就是window(其实这也能够叫函数的默认绑定,在后面我会介绍),函数控制台输出的就是window.a,函数内部即便没有定义变量,一样也是能够输出a的值,这其中也涉及到了做用域链的相关知识点,由内向外搜索,这里就不解释了,这个能够本身去了解。
加大一点难度,看看这个例子,可能会让你开始有点迷惑,我本身在不是很理解this在函数中的调用,是很迷惑的,不懂,相关知识点一遍一遍的反复的看,你们来看看,是上面的例子的改版:app
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
默认绑定code
函数独立调用,直接使用不带任何修饰的函数引用进行调用,其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的逻辑提供很好的帮助