函数的this指向谁,和函数在哪里被定义的,函数在哪里被执行的没有半毛钱关系,只遵守下面的规律:
在非严格模式中:
1、自执行函数里面,this永远指向window;
<script> var a = 1; var o = { a: 2, fn: (function(){ //自执行函数,在定义的时候就已经执行啦 console.log('自执行函数里面是window',this.a); //自执行函数里面的this指向的是window return function() { // 但是这里的this 指向的是谁调用的这个函数 console.log('但是还是要具体问题具体分析',this.a) } })() } o.fn(); </script>
结果请看
2、给元素的某一个行为绑定方法,当行为触发所调用的函数里面this指向的该dom 元素;
<script> var dd = document.getElementById('dd'); function f1 () { console.log(this); } dd.onclick=f1; // 点击的那个dom对象 </script>
但是我要是稍微改一下:
<script> var dd=document.getElementById('dd'); function fn () { console.log(this); } dd.onclick=function(){ console.log(this); // dom 对象 fn(); // window ,这时候就看该函数是被谁调用的啦 } </script>
3、看看函数执行有咩有 . ,如果有则是前面的那个,如果没有则是window
4、在构造函数里面,this 指向的是当前的实例;
<script> function fn() { console.log(this); }; function ff () { this.name="杜俊成"; this.say=function(){ console.log(this); // this指向该构造函数的原型 fn() // window ,因为fn 函数的直接调用者是window, } } var a = new ff(); a.say(); </script>
5、使用call / apply 改变了this 的指向;(关于call 和 apply 想一劳永逸的搞明白吗?请看我的一篇文章)
严格模式:
1、自执行函数里面,this永远指向undefined;
<script> var obj ={ fn:(function(){ // this => undefined console.log(this) return function(){ // this=> obk console.log(this); } })() } obj.fn; //obj.fn 的方法在声明的时候就已经被执行了, window obj.fn(); //obj.fn的自执行方法返回的方法执行 obj </script>
2、看前面有咩有 . ,如果有则是前面的那个,如果没有则是undefined
总结就是:严格模式和非严格模式的区别:当调用主体不明时,严格模式是undefined,非严格模式是window
<script> 'use strict'; function fn(){ alert(this); } /*非严格模式*/ fn.call()//this - window; fn.call(null)//this - window; fn.call(undefined);//this -undefined /*严格模式下,给call或apply第一个参数传谁this就是谁,不传就是undefined*/ fn.call() //this - undefined; fn.call(null) //this -null; fn.call(undefined) //this-undefined </script>
es6 新增的箭头函数比较特殊。我们使用function定义的函数,在定义时,它并不知道这个this会指向哪里,只有在运行的时候才能明确this的值。
箭头函数本身不具有this,它会直接绑定到它的词法作用域内的this,也就是定义它时的作用域内的this值。所以试图使用apply,call等方法修改箭头函数的this是不会成功的,因为箭头函数自身没有this。所以我们来看下面一段代码:
var func = () => { console.log(this); } func(); // Window func.apply({}); // Window
function func() { console.log(this) return () => {console.log(this)} }; func()() // Window // Window func.apply({a:1})() // Object {a:1} // Object {a:1} func.apply({a:2})() // Object {a:2} // Object {a:2}
通过这段代码,我们应该可以明确的看出来,箭头函数是直接使用的它词法作用域内的this,也就是定义它时的作用域内的this。当我们修改它的作用域内的this值,也就是func的this值时,在箭头函数内也可以反映出来。用作对比,我们看下使用function定义的函数:
function func() { console.log(this) return function(){ console.log(this) } }; func()() //window window func.apply({a:1})() // {a:1} window func.apply({a:2})() // {a:2} window
github地址:https://github.com/dujuncheng