JS 中的 this 总结

Posted go4it

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS 中的 this 总结相关的知识,希望对你有一定的参考价值。

JavaScript 中的 this:
this指向是在运行函数时确定的,而不是定义函数时候确定的
匿名函数的执行环境具有全局性,因此其this 对象通常指向window(在通过call()或apply()改变函数执行环境的情况下,this 就会指向其他对象)

全局上下文:无论是否在严格模式下,在全局执行上下文中(在任何函数体外)this都指代全局对象

    如:
        1、console.log(this === window); // true
        2、var girl={name:"amy",testThis:this}; console.log(girl.testThis); // window
          (可理解为:var girl=new Object(); girl.name="amy"; girl.testThis=this;(指向window)


函数上下文:在函数内部,this的取值取决于函数被调用的方式

    1、简单调用:
    function f1(){
      return this;
    }
    f1() === window; //在浏览器中,全局对象是window
    非严格模式下,且this的值不是由该调用设置时(具体说就是不由该调用通过 call、apply、bind 这些方法来设置),this的值默认指向全局对象 严格模式下,this将保持它进入执行上下文时的值 所以默认为undefined
    
    2、如果要想把 this 的值从一个上下文传到另一个,就要用 call 或者apply 方法
    
    3、bind方法:
    ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的
    
    4、箭头函数:this与封闭词法上下文的this保持一致(即this被设置为它创建时的上下文)。如果将this的值传给call、bind、apply,它将被忽略,不过仍然可以为为调用添加参数,不过第一个参数应设置为null
    
    5、作为对象的方法:当作为对象的方法被调用时,它们的this是调用该函数的对象,并且此时this的绑定只受最靠近的成员引用的影响
    
    6、原型链中的this:this指向的是调用该方法的对象,就像该方法在对象上一样

    7、getter(与setter)中的this:用作getter(或setter)的函数会把this绑定到获取(或设置)属性的对象上

    8、作为构造函数:this被绑定到正在构造的新对象(虽然构造器返回的默认值是this所指的那个对象,但它仍可以手动返回其他的对象)
    
    9、作为一个DOM事件处理函数:this指向触发事件的元素
    
    10、作为一个内联事件处理函数:this指向监听器所在的DOM元素
        如:
            1、<button onclick="alert(this.tagName.toLowerCase());"> Show this </button> this指向button(注意只有外层代码中的this是这样设置的)
            
            2、<button onclick="alert((function(){return this})());">  Show inner this </button> 这种情况下,没有设置内部函数的this,相当于函数简单调用的情况,所以它指向global/window对象

 

部分代码示例:

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>This</title>
  6 </head>
  7 <body>
  8 
  9 <script>
 10     //全局上下文:无论是否在严格模式下,在全局执行上下文中(在任何函数体外)this都指代全局对象 
 11     var girl={
 12         name:"amy",
 13         testThis:this
 14     };
 15     /*
 16         可理解为:
 17         var girl=new Ojbect();
 18         girl.name="amy";
 19         girl.testThis=this;
 20     */
 21     console.log(girl.testThis);//window
 22 </script>
 23 
 24 <script>
 25     console.log("JS 是基于词法作用域的语言,函数在定义它的作用域中执行,而不是在调用它的作用域中执行");
 26     console.log("类的方法默认是不会绑定 this 的,作为对象的方法:当作为对象的方法被调用时,它们的this是调用该函数的对象,并且this的绑定只受最靠近的成员引用的影响");
 27     console.log("-----------About Amy --------------");
 28     var Amy={
 29             name:"Amy",
 30             sex:"girl",
 31             amyOutter:function(){
 32                 console.log("amyOutter:",this);
 33                 return function(){
 34                     console.log("amyAnonymous:",this);
 35                 };
 36             }
 37         };
 38     console.log("----Amy.func amyOutter -----");
 39     var amy_anony=Amy.amyOutter();
 40     //输出: amyOutter: {name: "Amy", sex: "girl", amyOutter: ƒ}
 41     // 解析:作为对象的方法调用
 42 
 43     console.log("----Amy.func amyOutter quote-----");
 44     var quote=Amy.amyOutter;//获取Amy.amyOutter函数的引用
 45     quote();
 46     //输出:amyOutter: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 47     // 解析:这里相当于简单调用
 48     
 49     console.log("----Amy.func amyAnonymous-----");
 50     amy_anony();
 51     //输出: amyAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 52     // 解析:直接调用返回的匿名函数
 53 
 54     amy_anony.call(Amy);
 55     //输出: amyAnonymous: {name: "Amy", sex: "girl", amyOutter: ƒ}
 56     // 解析:Amy用call调用返回的匿名函数
 57     
 58 </script>
 59 
 60 <script>
 61     console.log("-----------About Mike -----------");
 62     var Mike={
 63         name:"Mike",
 64         sex:"boy",
 65         mikeOutter:function(){
 66             console.log("mikeOutter:",this);
 67             (function(){
 68                 console.log("mikeAnonymous:",this);
 69             })();
 70         }
 71     };
 72 
 73     console.log("----Mike.func mikeOutter---");
 74     Mike.mikeOutter();
 75     //输出: mikeOutter: {name: "Mike", sex: "boy", mikeOutter: ƒ}
 76     // 解析:作为对象的方法调用  
 77     //输出: mikeAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 78     // 输出:window 解析:匿名函数被调用
 79 
 80     console.log("----Mike.func mikeOutter quote-----");
 81     var quote=Mike.mikeOutter;//获取Mike.mikeOutter函数的引用
 82     quote();
 83     //输出:mikeOutter: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 84     // 解析:这里相当于简单调用
 85     //输出: mikeAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 86     // 解析:匿名函数被调用
 87 
 88     console.log("---Mike func call---");
 89     Mike.mikeOutter.call(Amy);
 90     //输出: mikeOutter: {name: "Amy", sex: "girl", amyOutter: ƒ}
 91     // 解析:Amy 用call调用返回的匿名函数 
 92     //输出:mikeAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
 93     // 解析:匿名函数被调用
 94 
 95 </script>
 96 
 97 <script>
 98     console.log("-----------About Guang -----------");
 99     var Guang={
100         name:"Guang",
101         sex:"boy",
102         GuangOutterOne:function(){
103             console.log("GuangOutterOne:",this);
104             var that=this;
105             // 正确 that 中保留了对 this 的引用
106             this.GuangOutterTwo(function(){
107                 that.GuangOutterThree();                
108             });
109             
110             // 正确 匿名函数直接绑定 this
111             // this.GuangOutterTwo(function(){
112             //     this.GuangOutterThree();                
113             // }.bind(this));
114 
115             // 出错 匿名函数作参数 this 为 window ,window 无 GuangOutterThree 方法
116             // this.GuangOutterTwo(function(){
117             //     this.GuangOutterThree();                
118             // });
119         },
120         GuangOutterTwo:function(cb){
121             console.log("GuangOutterTwo:",this);
122             cb();
123         },
124         GuangOutterThree:function(){
125             console.log("GuangOutterThree:",this);
126         }
127     };
128 
129     console.log("----Guang.func GuangOutterOne---");
130     Guang.GuangOutterOne();
131     //输出:GuangOutterOne: {name: "Guang", sex: "boy", GuangOutterOne: ƒ, GuangOutterTwo: ƒ, GuangOutterThree: ƒ} 
132     //解析:作为对象的方法调用  
133 
134     //输出: GuangOutterTwo: {name: "Guang", sex: "boy", GuangOutterOne: ƒ, GuangOutterTwo: ƒ, GuangOutterThree: ƒ}
135     //解析: GuangOutterOne 中的 this 指向 Guang 调用 Guang 中的 GuangOutterTwo 方法
136 
137     //输出: GuangOutterThree: {name: "Guang", sex: "boy", GuangOutterOne: ƒ, GuangOutterTwo: ƒ, GuangOutterThree: ƒ}
138     //解析: that 保留对 this 的引用 调用 Guang 中的 GuangOutterTwo 方法
139    
140 
141 </script>
142 
143 <script>
144     console.log("JS 是基于词法作用域的语言,函数在定义它的作用域中执行,而不是在调用它的作用域中执行");
145     console.log("箭头函数:this与封闭词法上下文的this保持一致(即this 被设置为他被创建时的上下文)");
146     var foo=(()=>this);
147     /*
148         可以把箭头函数看成是
149         var foo=function(){
150             //other code
151             return this;
152             //此处this所在的函数被创建时是在全局环境中 因为 this被设置为他被创建时的上下文 所以 this就被设置为window
153         };
154     */
155     // 由下可见 无论如何,foo 中的 this 都被设置为他被创建时的上下文(在上面的例子中,就是全局对象)
156     // 注意:对于箭头函数 如果将this传递给call、bind、或者apply,它将被忽略 不过你仍然可以为调用添加参数,不过第一个参数(thisArg)应该设置为null
157     var obj = {foo: foo};
158     console.log("直接调用:",foo()===window,", call调用:",obj.foo() === window,", apply调用:",foo.call(obj) === window,", bind绑定:",foo.bind(obj)() === window); // true true true true
159     
160    //这同样适用于在其他函数内创建的箭头函数:这些箭头函数的this被设置为封闭的词法上下文的
161     console.log("-----------About John ------------------");
162     var John={
163         name:"John",
164         johnOutter:function(){
165             //console.log("johnOutter",this);//johnOutter中的this具体情况可参考上面的Amy和Mike实例
166             var x=(()=>this);
167             //此处this所在的函数被创建时是在johnOutter中  因为 this被设置为他被创建时的上下文 所以 this就被设置为 johnOutter 函数中的this
168             return x;
169         }
170     }
171 
172     var fn=John.johnOutter();//获取返回的函数 若去掉johnOutter中console.log语句的注释 输出:John 解析:解析:作为对象的方法调用 
173     console.log("John.johnOutter():",fn());
174     //输出:John.johnOutter(): Object { name: "John", johnOutter: johnOutter() }
175     //解析:此时johnOutter函数由John调用 所以johnOutter函数中的this为John,而箭头函数的this被设置为johnOutter的this
176 
177     var quote=John.johnOutter;//获取John.johnOutter函数的引用
178     console.log("quote:",quote()());
179     //输出:window 
180     //解析:此时quote获取johnOutter的引用,quote()相当于简单调用,所以johnOutter函数中的this为window,而箭头函数的this被设置为johnOutter的this
181     
182     /**
183      * 对于箭头函数:
184      * 1、确定箭头函数是在哪个执行环境中被创建的
185      * 2、根据执行环境确定this被设置为哪个执行环境
186      * 3、最后对函数的调用参考对象中的方法调用即可
187      * 总结可以简单理解为:
188      * 箭头函数的this在全局执行上下文创建时 它的this就是全局上下文中的this 
189      * 箭头函数的this在全局执行上下文创建时 它的this就是全局上下文中的this 
190      */
191 
192 </script>
193 
194 </body>
195 </html>

 

以上是关于JS 中的 this 总结的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——JS中的面向对象编程

VSCode自定义代码片段9——JS中的面向对象编程

JS 中的 this 总结

JS中的this的应用总结

js数组遍历方法总结

ngx-translate实现国际化:this.translate.use()this.translate.get()this.translate.instant()onLangChange(代码片段