1

This的设计

Javascript 是允许在函数体内引用当前环境的其他变量,因此函数可以在不同的运行环境执行,所以我们就需要一种机制,能够在函数内获得当前运行环境,由此诞生了 this ,它的设计目的就是指向函数运行时所在的环境。

如何判断This指向

1.默认绑定

严格模式:

(() => {  
    "use strict"  
    function foo() {    
        console.log(this.name);
    };  
    var name = "keys";  
    foo(); })();
    // Uncaught TypeError TypeError: Cannot read properties of undefined (reading 'name')
    // at foo (d:\web\index.html:16:26)
    // at <anonymous> (d:\web\index.html:19:5)
    // at <anonymous> (d:\web\index.html:19:14)

在严格模式下This不会绑定为默认绑定到Window上,而是会默认绑定为undefined,从而无法访问到name。

    function foo() {    
        console.log(this.name);
    };  
    var name = "keys";  
    (() => {  
    "use strict"  
    foo(); }
    )();
    //keys

但是在严格模式下调用函数则不会影响默认绑定。

非严格模式

This默认绑定到全局对象

    var name = 'keys'
    function foo(){
        console.log(this.name);//keys
        console.log(this);//Window
        console.log(window);//Window
    }
    foo();

2.隐式绑定

对象方法:通过对象属性执行函数时,此时隐式绑定规则会将 this 绑定到对象上;

一层作用域时:this指的是该对象

    var name = 'keys';
    function foo() {  
        console.log(this.name);
    }
    var obj = {  
        name: 'objkeys',
        foo
    }
    obj.foo(); //objkeys
    foo();//keys

obj.foo()是由对象obj调用的所以this隐式绑定到obj上,所以第一次输出objkeys. foo()是在全局上调用的所以,this绑定到全局对象Window上,输出keys。

多层作用域链时,this指的是距离方法最近的一层对象

    var name = 'keys';
    function foo() {  
        console.log(this.name);
    }
    var obj = {  
        name: 'objkeys',
        obj1:{
            name:'obj1keys',
            foo
        }
    }
    obj.obj1.foo(); //obj1keys

因为foo在对象obj,obj1中,所以this默认绑定到最近的对象obj1中,所以属性name为obj1keys。

特别地:

var name = 'keys';
    var obj = {  
        name: 'objkeys',
        obj1:{
            name:'obj1keys',
            foo: function(){
                console.log(this.name
            }
        }
    }
    obj.obj1.foo(); //obj1keys

    var obj2 = obj.obj1.foo;
    obj2();//keys

通过赋值将对象里的方法给了obj2,并未真正执行当前函数,而后在全局环境下执行函数,所以this指向全局对象Window,输出keys。

3.显示绑定

通过call、bind、apply
call:使用一个指定的 this 和若干个指定的参数调用某个函数或方法.
如果call、apple、bind的绑定对象是null或者undefined,那么实际上在调用时这些值都会被忽略,所以使用的是默认绑定规则,默认绑定到Window。

    function foo() {  
        console.log(this.name);
    }
    var obj = {  name: 'objkeys',}
    var obj1 = {  name: 'objkeys1'}
    var name = 'keys';
    foo.call(obj); // objkeys
    foo.call()//keys

4.构造函数的调用,this指的是实例化的新对象

    var name = 'keys';
    function Foo(){
        this.name = 'keys1';
        this.type = 'type';
    }
    var foo = new Foo();
    console.log(foo.name);//keys1

5.匿名函数

this指向的是全局对象window

        var name = 'keys';
        var obj = {
            name:'objkeys',
            foo:(function(){
                console.log(this.name);
                })()
        }
        obj.foo;//keys

6.箭头函数

ES6新增了一种函数类型:箭头函数,它和普通函数最不同的一点就是对于箭头函数的 this 指向,是根据它外层(函数/全局)作用域来决定。因为其本身没有this所以会按照外层作用域来执行。this绑定的是最近一层非箭头函数的this,否则this的值则被设置为全局对象。

 var name = 'window';
        var obj = {
            name: 'objkey',
            Foo: function(){
                // var self = this;
                var foo = () => {
                    // console.log(self.name);
                    console.log(this.name);
                }
                foo();
            },
            Foo1: () => {
                console.log(this.name);
            },
            Foo2:function(){
                console.log(this.name);
            }
        }
        obj.Foo(); // 'objkey'
        obj.Foo1();// 'window'
        obj.Foo2(); // 'objkey'

7.规则优先级

1、new绑定var obj = new Foo();this绑定新的对象上
2、显示绑定var obj = foo.call(bar);this绑定到指定对象上,若指定对象为null/undefined或着没传,则使用默认绑定规则
3、隐式绑定
var obj = bar.foo();this绑定到调用方法的对象上
4、默认绑定foo();this在严格模式下绑定到undefined

8.DOM事件处理函数中this的指向

<button class="button">onclick</button>
<ul class="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    var button = document.querySelector('button');
        button.onclick = function(e){
        console.log(this);
        console.log(this === e.currentTarget); // true
        }
         var list = document.querySelector('.list');
         list.addEventListener('click', function(e){
        console.log(this === list); // true
        console.log(this === e.currentTarget); // true
        console.log(this);
        console.log(e.target);
        }, false);
</script>

小结

1.普通函数的调用,this指向的是window
2.对象方法的调用,this指的是该对象,且是最近的对象
3.显示绑定call调用,this指向参数中的对象
4.构造函数的调用,this指的是实例化的新对象
5.匿名函数的调用,this指向的是全局对象window,定时器相当于匿名函数
6.箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this,否则this的值则被设置为全局对象
7.new>显示>隐式>默认
8.onclick和addEventerListener是指向绑定事件的元素

参考网址:
https://blog.csdn.net/weixin_30980795/article/details/107448842
https://baijiahao.baidu.com/s?id=1763115725232602497&wfr=spid...


keys
4 声望0 粉丝