标签:win 默认 cli ons 详细 绑定 app apply 对象
在javascript中this的指向一直是前端同事的心头病,也同时是各面试题的首选,现在我们就来总结一下js中this的指向。首先需要了解一下几个概念:
1:全局变量默认挂载在window对象下
2:一般情况下this指向它的调用者
3:es6的箭头函数中,this指向创建者,并非调用者
4:通过call、apply、bind可以改改变this的指向
下面我们具体分析一下
1:在函数调用时
(非严格模式)
1 const func = function () { 2 console.log(this); 3 const func2 = function () { 4 console.log(this); 5 }; 6 func2(); //Window 7 }; 8 func(); //Window
(严格模式)
1 ‘use strict‘ 2 const func = function () { 3 console.log(this); 4 const func2 = function () { 5 console.log(this); 6 }; 7 func2(); //undefined 8 }; 9 func(); //undefined
结合第四和第一两条规则:func这个函数是全局的,默认挂载在window对象下,this指向它的调用者即window,所以输出window对象,但是在严格模式下,this不允许指向全局变量window,所以输出为undefined(func2在函数直接调用时默认指向了全局window,其实这属于javascript设计上的缺陷,正确的设计方式是内部函数的this 应该绑定到其外层函数对应的对象上,为了规避这一设计缺陷,聪明的 JavaScript 程序员想出了变量替代的方法,约定俗成,该变量一般被命名为 that。这种方式在接下来会讲到)。
2:作为对象方法
1 const user = { 2 3 userName: ‘小张‘, 4 age: 18, 5 selfIntroduction: function () { 6 const str = ‘我的名字是:‘ + this.userName + ",年龄是:" + this.age; 7 console.log(str); 8 9 const loop = function () { 10 console.log(‘我的名字是:‘ + this.userName + ",年龄是:" + this.age); 11 }; 12 13 loop(); //我的名字是:undefined,年龄是:undefined 14 15 } 16 }; 17 18 user.selfIntroduction(); //我的名字是:小张,年龄是:18
按照咱的第一条规则,this指向他的调用者,selfIntroduction()方法的调用者是user,所以在selfIntroduction()方法内部this指向了他的父对象即user,而loop方法输出的为undefined的原因就是我在上面所说的javascript的设计缺陷了,在这种情况下,我们通常选择在selfIntroduction()方法里将this缓存下来。
1 const user = { 2 userName: ‘小张‘, 3 age: 18, 4 selfIntroduction: function () { 5 const str = ‘我的名字是:‘ + this.userName + ",年龄是:" + this.age; 6 console.log(str); 7 8 const that=this; 9 10 const loop = function () { 11 console.log(‘我的名字是:‘ + that.userName + ",年龄是:" + that.age); 12 }; 13 14 loop(); //我的名字是:小张,年龄是:18 15 16 } 17 }; 18 19 user.selfIntroduction(); //我的名字是:小张,年龄是:18
此时loop的this指向就理想了。
1 const user={ 2 3 userName:‘小张‘, 4 age:18, 5 selfIntroduction:function(){ 6 const str=‘我的名字是:‘+this.userName+",年龄是:"+this.age; 7 console.log(str); 8 } 9 }; 10 11 const other =user.selfIntroduction; 12 other(); //我的名字是:undefined,年龄是:undefined 13 14 const data={ 15 userName:‘小李‘, 16 age:19, 17 }; 18 data.selfIntroduction=user.selfIntroduction; 19 data.selfIntroduction(); //我的名字是:小李,年龄是:19
在看这段代码,将selfIntroduction()赋值给了全局变量other,调用other()方法,other挂载在全局函数window对象下,window对象下没有userName 和 age 这两个属性,所以输出为undefined。第二段代码,申明了data对象,包含了username和age属性,记住我们的第二条规则一般情况下this指向它的调用者,大家就明白了,data是selfIntroduction()的函数的调用者,所以输出了data的userName和age。
3:在html里作为事件触发
<body> <div id="btn">点击我</div> </body>
1 const btn=document.getElementById(‘btn‘); 2 3 btn.addEventListener(‘click‘,function () { 4 console.log(this); //<div id="btn">点击我</div> 5 })
在种情况其实也是遵循了第二条规则一般情况下this指向它的调用者,this指向了事件的事件源即event。
4:new关键字(构造函数)
1 const fun=function(userName){ 2 this.userName=userName; 3 } 4 5 const user=new fun(‘郭德纲‘); 6 7 console.log(user.userName); //郭德纲
这个就不多赘述了,new关键字构造了一个对象实例,赋值给了user,所以userName就成为了user对象的属性。
5:es6(箭头函数)
1 const func1=()=>{ 2 3 console.log(this); 4 5 }; 6 7 func1(); //Window
1 const data={ 2 userName:‘校长‘, 3 selfIntroduction:function(){ 4 console.log(this); //Object {userName: "校长", selfIntroduction: function} 5 6 const func2=()=>{ 7 console.log(this); //Object {userName: "校长", selfIntroduction: function} 8 } 9 10 func2(); 11 } 12 13 } 14 15 data.selfIntroduction();
大家在看看我开头说的第三条准则:es6的箭头函数中,this指向创建者,并非调用者,fun1 在全局函数下创建,所以this指向全局window,而fun2在对象data下创建,this指向data对象,所以在func2函数内部this指向data对象,个人认为es6的箭头函数的this指向是对我上面所说的javascript设计缺陷的改进,(个人认知)。
6:改变this的指向
call、apply、bind这三个函数是可以人为的改变函数的this指向的,在这里就不多说这三者的区别了,在往后的博客里我会详细解释这三者的区别的。现在先拿一个来举一个例子
1 const func=function(){ 2 console.log(this); 3 }; 4 5 func(); //window 6 7 func.apply({userName:"郭德纲"}); //Object {userName: "郭德纲"}
这三个方法都是可以人为的改变this的指向,区别是call、apply会将该方法绑定this之后立即执行,而bind方法会返回一个可执行的函数。
说这很多总结起来就是我开头说的4点
1:全局变量默认挂载在window对象下
2:一般情况下this指向它的调用者
3:es6的箭头函数中,this指向创建者,并非调用者
4:通过call、apply、bind可以改改变this的指向
说实话第一次写博客,确实挺忐忑的,会不会有人看我的博客?会不会写的不正确?……想好多了,总结了:不好的地方欢迎指正。
标签:win 默认 cli ons 详细 绑定 app apply 对象
原文地址:http://www.cnblogs.com/wuhongwei/p/7210944.html